Update Rhino geometry in real time from a C# component

Hi @mrhe, I’m the author of Tarsier (source code) - which attempts similar goals to what you’re working on. I have a few suggestions that may help improve your performance.

  1. Output a list of GH_Point instead of Point3d. You can do this with Linq, DA.SetDataList(0, pointCloud.Select(x => new GH_Point(x));. As a general rule this will massively increase performance when you’re outputting objects, as it saves Grasshopper having to cast and create them for you.
  2. Grasshopper doesn’t natively implement the rhino PointCloud class, so I created one with Tarsier to avoid exactly this (creation of hundreds of thousands of points every frame). In proper Grasshopper fashion, it previews as a Rhino point cloud, has a custom preview(thickness), has bake/set, deconstruct/reconstruct, and dynamic casting to RhinoCommon’s point cloud class, (or other implementations) so it can be interoperable. The code for this is here

From memory, with the two above considerations loading a full frame was around 10-20ms on a mediocre PC. In your case, I expect you’ll see an enormous performance gain just by using the single line of Linq I mentioned in (1).

(2) is primarily aimed at addressing the draw time in Rhino, as a point cloud renders significantly faster than 100,000 individual points. And, since Grasshopper also runs on Rhino’s main thread, this affects the update speed.

A simple benchmark of these this technique (1) using 100,000 randomly generated points.

Awesome, so we’ve gone from 565 ms to 12 ms. 4700% faster!

Now, unfortunately because we’re drawing all those 100,000 individual points, just one of those components enabled will show some pretty poor display performance!
Time to regen viewport 100 times = 5.41 seconds. (18.50 FPS)

So to address (2) - let’s output a point cloud and write a display function for it. Another advantage of this is that you can include the Kinect color directly into the point cloud rather than managing two different lists. Constructing and outputting the point cloud results in similar (slightly better) to the array method. In this case I’ve written the renderer as a separate component, but you’d be just as easily able to embed it in the receiver, too.

Since the renderer doesn’t do any computing in RunScript it doesn’t show a computation time.
But, when we test viewport speed again with !_TestMaxSpeed, we see:
Time to regen viewport 100 times = 0.83 seconds. (120.77 FPS), or about 600% rendering performance.

I’ve attached the example demonstrating this.

pointCloud_performance.gh (8.2 KB)

Cheers
Cam

7 Likes