Conduit performance

Hi,
I am working on simple conduit that is supposed to find specific points in the project and draw simple spheres in given location. Problem is that number of these points can be several thousands and I noticed significant lagging after I reached ~ 2k points.

I was wondering how is possible that if I generate same spheres in the project it works seamlesly, but when same objects are rendered through conduit it downgrades performance significantly and if I can do something about it.

Thank you

Can you post your code? I find you can generate quite a lot of geometry before any noticeable lag usually.

Did you try to merge all spheres into a single merged mesh (outside your overloaded displayConduit method, of course, everything there must be lean and simple to avoid “lagging”). This should significantly speed up things, as long as draw calls will be massively reduced

Also, If you only want to show “points”, DrawPoints instead of spheres will significantly increase performance, I have used this method to display hundred of thousand of points with good performance.

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Display_DisplayPipeline_DrawPoints_2.htm

But again, its very important to keed all possible logic outside Display Pipeline draw calls (i.e, PostDrawObjects, BeforeDrawObjects et. al.)

1 Like

I did not because I would have to give up on dynamic transformation when user drags one of those points (I would like to avoid that if possible). I am also really careful about creating anything in conduit functions or making it too complex. I actually thought that simple iterating through this many objects is the reason it becomes too slow…

Here is the code I use.
Both mesh and material that I use for displaying spheres is created in constructor

protected override void PreDrawObjects(DrawEventArgs e)
{
    base.PreDrawObjects(e);
                
    foreach (var o in e.RhinoDoc.Objects)
    {
       if (_plugin.CurrentConduitData.ContainsKey(o.Id))
       {
            var data = _plugin.CurrentConduitData[o.Id];
            Transform dynamicTransform;
            if (o.GetDynamicTransform(out dynamicTransform))
            {
                data.Display(e.Display, dynamicTransform);
            }
            else
            {
                data.Display(e.Display, null);
            }
        }
    }
}

//Display method of object stored in _plugin.CurrentConduitData dictionary
public void Display(DisplayPipeline display, Transform? transform)
{
    var toDraw = _sphereMesh;
    if (transform.HasValue)
    {
        toDraw = toDraw.DuplicateMesh();
        toDraw.Transform(transform.Value);
    }
    display.DrawMeshShaded(toDraw, _material);
}

Thank you for help!

There’s quite a lot extra here that I don’t have access too. Would you be able to bundle this up in a small VS project (without any code you don’t wish to share) and an accompanying rhinodoc example?

– Callum

Hi @h.kirchner94,

To speed up display, you might consider drawing in a different display conduit channel. DisplayPipeline.PreDrawObjects probably isn’t a good place for you to be drawing, as depth writing and testing are on. Try drawing in the DisplayPipeline.DrawForeground channel and see if get the results you want.

– Dale

Test.zip (276.2 KB)

Here is a test project with file containing ~2200 points that you can just open to see.
Plugin should simply show half transparent sphere arounf each point.

Thank you, I tryed but I didn’t see any significant improvement. I created a testing project to demonstrate my problem. Maybe I am missing something obvious.

I built the project and installed it into a fresh version of Rhino 7 without any other plugins, for me each run of the PostDrawObjects method took ~80ms, had no noticeable lag, does it take significantly longer for you?

The only speed issue I thought I found was each ConduitData creating its own DisplayMaterial, but after I externalised that it didn’t seem any faster, which is odd as I’ve found that to slow down my DisplayConduits before.

The only other thing I noticed which bothered me was that the mesh jumps after I finish dragging it, which just required an extra check in the RhinoDoc_AddRhinoObject method.

    private void RhinoDoc_AddRhinoObject(object sender, RhinoObjectEventArgs e)
    {
        if(e.TheObject.ObjectType == ObjectType.Point)
        {
            if (!_plugin.ConduitDataDictionary.ContainsKey(e.TheObject.Id))
            {
                _plugin.ConduitDataDictionary[e.TheObject.Id] = new ConduitData(((Point)e.TheObject.Geometry).Location);
                e.TheObject.Document.Views.Redraw();
            }
        }
    }

– Callum

How often do you end up in the case where a transforn exists? Duplicating and transforming meshes inside of a conduit is not a light operation at all. You would be much better off calling PushModelTransform/PopModelTransform on the display pipeline in that case

1 Like

For me it takes around 260ms. I have to say I don’t work on the most powerful PC though (but also not total trash - 4xtimes slower feels way too much). What surprises me the most is the fact that if put 2500 spheres to the project and let Rhino draw it it is smooth, but when I try to display same objects with conduit it gets slow.

It’s really rare. Those points should be independent and can be moved but it doesn’t happen often. How I said in the previous answer - what surprises me the most is the fact that if put 2500 spheres to the project and let Rhino draw it it is smooth, but when I try to display same objects with conduit it gets slow

We try and do a lot of optimizations for geometry that lives in the document as we know it is most likely going to stick around for a while.