Draw To Screen Space Foreground From DrawViewportWires

Hi All,

I’m experimenting with implementing DrawViewportWires in GHPython for drawing e.g. legends on top of 3D geometry generated in Grasshopper. Here’s a quick example:

The issue I’m trying to resolve is that the rectangles (drawn with Draw2dRectangle ) are drawn behind the 3D geometry that is drawn by Grasshopper (though it still appears to obscure the wires of the 3D mesh), while the text is drawn in the foreground:

Here’s a minimal example and file of this behaviour:


201125_DrawRectangle2d_00.gh (4.9 KB)

I can see that this issue has been brought up previously by @andheum. But I’ve not been able to find any examples/code that demonstrate how one has resolved this (notably how to “add a callback to the DisplayPipeline.DrawForeground event”). I should also mention that I’ve been given great pointers by @dave_stasiuk and @tom_svilans on how they draw to the foreground from a display conduit in a compiled component. But before going down that path, I just wanted to make sure that I’m not missing something here.

So, is it possible to always draw to the screen space foreground from DrawViewportWires?

Best,

Anders

1 Like

Apologies for bumping. Maybe @stevebaer, @piac, or @DavidRutten have some suggestions?

You really want to have HUD type display done in the DrawForeGround stage of drawing. DrawForeground occurs after DrawViewportWires and has depth testing turned off which is exactly what you want with a HUD.

Here is what I was able to cook up. It’s not as clean as just having a DrawForeground override in the component class, but it should work. Let me know if you have any questions.

201125_DrawRectangle2d_00.gh (16.1 KB)

@piac helped me make a cleaner version.
Here’s an update 201125_DrawRectangle2d_00.gh (13.6 KB)

2 Likes

This is fantastic, thanks so much! Will have a go at implementing this into the legend component ASAP. You guys rock :metal:

I ended up using a combination of the two methods: Implementing both the hack to pipe into DrawViewportWires and the __enter__/__exit__ methods to add/remove the DrawForeground method. This means the component still behaves like a “normal” Grasshopper component (i.e. one can turn Preview off to stop drawing etc.).

It seems to work okay so far:

And here’s the minimal case again, with these edits:
201203_DrawRectangle2d_02.gh (5.3 KB)

Thanks again guys, very much appreciated :beers:

1 Like

I took a stab at a HUD display leveraging the DisplayPipeline.DrawForeground event handler in C#. Basic functionality works as expected, but I have a few questions on how to further customize it:

  1. The event fires for each viewport separately. Is there a way to limit the HUD to only the active viewport?

  2. Fill color of 2D shapes respects transparency, 2D text color ignores it. Is this intended behavior?

  3. Using the ViewCaptureToFile command with increased resolution doesn’t scale the HUD correctly and causes it to be drawn multiple times. Any ideas how to address this?
    ScreenCaptureToFile:


    ViewCaptureToFile:

Any ideas @AndersDeleuran @stevebaer ?

201208_DrawRectangle2d_03.gh (6.2 KB)

I added this conditional to only render in the active viewport:

Afraid I don’t have any ideas on the other two issues.

1 Like

Thanks Anders,

works like a charm! C# equivalent below if anyone is interested:

    private void DrawForeground(object sender, DrawEventArgs e)
    {
        if (e.Viewport.Id == Rhino.RhinoDoc.ActiveDoc.Views.ActiveView.ActiveViewportID)
        {
         // do magic
        }
    }
1 Like

Using the doc that gets passed as part of the DrawEventArgs is better to use over ActiveDoc

1 Like

Thanks @stevebaer, fixed that part:

private void DrawForeground(object sender, DrawEventArgs e)
{
    if (e.Viewport.Id == e.RhinoDoc.Views.ActiveView.ActiveViewportID)
    {
     // do magic
    }
}

Any suggestions on how to attack the scaling and transparency issues?

Hi @stevebaer, @mrhe, I adapted a similar code based on the old forum, but I have some similar issues with geometries in Rhino and GH since I didn’t use DrawForeground, because of my limited C# knowledge. could you help me to fix it, please
Even in the Rendered mode is incomplete and sometimes disappeared.
Regards,
T.


DrawRec.gh (3.9 KB)

Hi @ThomasE,

to keep your dashboard consistently above the remaining 3d geometry you need to use the DrawForeground method. Here is what I did:

public override void BeforeRunScript()
  {
    _point.Clear();
    _box = BoundingBox.Empty;
    
    // Unregister & register new event
    Rhino.Display.DisplayPipeline.DrawForeground -= DrawForeground;
    Rhino.Display.DisplayPipeline.DrawForeground += DrawForeground;
  }


  public override BoundingBox ClippingBox
    {get{return _box;}}

  // Event function
  private void DrawForeground(object sender, Rhino.Display.DrawEventArgs e)
  {
    for (int i = 0; i < _point.Count; i++)
      DrawRec(e, _point[i]);
  }

  private void DrawRec(Rhino.Display.DrawEventArgs pipeline, Point3d point)
  {
    if (pipeline.Viewport.Id == pipeline.RhinoDoc.Views.ActiveView.ActiveViewportID)
    {
      Rectangle SQ = new Rectangle((int) point.X, (int) point.Y, 50, 50);
      pipeline.Display.Draw2dRectangle(SQ, Color.Black, 5, Color.LimeGreen);
    }
  }

This gets you 80% there. You will notice, however, that the dashboard is now persistent even if you remove the script from your document or switch to a different one. Ideally, you would unregister from the DrawForeground event handler in the following two cases but I only know how to do it from a compiled component. Maybe someone else can help you with the script component counterparts:

public override void DocumentContextChanged(GH_Document document, GH_DocumentContext context) {}

public override void RemovedFromDocument(GH_Document document) {}

image

drawForeground.gh (2.7 KB)

1 Like