How to draw thousands of objects quickly?

Hi,

I am using the display pipeline to draw thousands of brep objects. They can’t be baked as they are supposed to be a preview of a custom plugin’s commands. I find that it gets a bit slow, with two issues:

  • Low frame rate when moving the camera around.
  • Something, possibly caching, is happening when the objects are initially drawn because it makes the commands a few seconds slower while DrawBrepShaded method exists.

I tried converting the objects to meshes, which removed the few seconds wait at the cost of making the frame rate worse. I also tried merging them into a single mesh, which completely fixed the frame rate but made the initial draw significantly slower.

I’m not sure what to try next.

If it helps, these objects are identical in geometry apart from their position and rotation, allowing for the final result to be baked as block instances. They are quite simple in construction (see picture below). The previewed objects need to support colors unique to each, which probably makes it more difficult. Generally, most are the same few colors so an approach that groups them by that might be possible.

Thanks.

1 Like

Have you tried creating one block definition with one mesh and then create thousands of instances?

I have now. It’s one of the better options currently but still not optimal:

  • I’m having issues with drawn instances lingering around. It gets progressively slower when moving the camera. Might be something I’m missing with my implementation.
  • All the instances use the color of the definition’s objects as expected, but I would like multiple colors.

Post your code, hard to suggest improvements without it?

1 Like

Hey @YCoCg,

I’ve done quite a bit of DisplayPipeline, these pointers may help.

  1. Use Occlusion to make sure you’re not drawing any outside of the users view.
  2. If the user is far enough away from the box, you can always draw it as something simpler (maybe a dot), or even not at all.
  3. IIRC Breps have a PreviewMesh inside of them that is created when they are rendered, I think you can ask nicely for this to be created which you can then use instead of the brep
  4. Make sure you’re caching these boxes, or whatever, and not creating them on the fly.
  5. You could create a little timer inside the Draw call to make sure that if it goes over X ms you stop drawing to prevent slow frame rates.
  6. Use a single DisplayMaterial (if you can), they’re slow.
  7. If you can’t use a single DisplayMaterial sort by material and draw by them, i.e do your green, then red, then blue. It saves GPU time. It’s faster to sort and draw in order than without.
  8. I think you can use the same mesh and push transforms which would be WAY faster. Possibly with this.
4 Likes

This is useful.

  1. I didn’t consider I would need to handle occlusion myself and implementing it provides a good improvement for some camera positions.
  2. I experimented with this before your post, drawing wires for distant objects rather than shaded surfaces. I decided not to do this because it was distracting.
  3. I couldn’t find a way to generate this manually but I think it wouldn’t matter as the mesh has to be generated at some point before displaying (so no computational saving).
  4. Yes, they are all cached, the draw method loops over a list of geometrical objects and the calculate bounding box method is using an already generated bounding box.
  5. Haven’t tried it yet
  6. This is something I missed, the colored objects had their own individual materials. There is a very minor speedup to this from my testing.
  7. Good to know. I think currently my objects are in an acceptable order already though.
  8. Haven’t tried it yet

What I’ve currently settled on is to draw the objects as meshes which provides good initial performance, and displaying them as wires only during camera movement, using e.Display.IsDynamicDisplay.