Manifold Geometry // Многообразная Геометрия

Offscreen rendering in Analysis Situs

/ Просмотров: 74

There are two approaches to render an offscreen image in headless mode using the Analysis Situs framework:

  • Using VTK.
  • Using OpenCascade.
A range of offscreen-rendered thumbnails for a CAD assembly.

VTK-based offscreen rendering

Historically, the VTK-based approach was the first to be implemented. Because Analysis Situs comes with a VTK viewer by default, it is appealing to simply export the rendered scene state to a PNG file without displaying any GUI window. Fortunately, VTK allows for this, although it requires a bit of extra work:

  1. The render window (the instance of vtkRenderWindow class) should be initialized with a specific "offscreen rendering" flag.
  2. The VTK library should be compiled with VTK_DEFAULT_RENDER_WINDOW_HEADLESS CMake variable turned on.
VTK viewer of Analysis Situs with a shape prepared for offscreen rendering.

It is not very handy to have two VTK versions: one for interactive runs and another for completely headless mode. However, such a specifically prepared VTK version is required to work on a backend without any graphics hardware installed. If you have a shape that you want to render offscreen, you have two options:

  • Just draw it as an object in the "Geometric Set" and make a snapshot.
  • Set this shape as an active part to be able to configure its visual properties. Then make a snapshot.

Let's look at one trick how to use the imperative plotter to set a shape as an active part:

vtkSmartPointer<vtkImageData> GetSnapshot(const TopoDS_Shape& shape,
                                          ActAPI_PlotterEntry plotter)
{
  vtkSmartPointer<vtkImageData> snapshot;
  
  // Prepare the preview snapshot.
  Handle(asiUI_IV)
    ivPlotter = Handle(asiUI_IV)::DownCast( plotter.Access() );
  //
  if ( !ivPlotter.IsNull() )
  {
    ivPlotter->ERASE_ALL();
    ivPlotter->DRAW_SHAPE_AS_PART_ON();
    ivPlotter->REDRAW_SHAPE("part", shape, Color_Default);
    ivPlotter->DRAW_SHAPE_AS_PART_OFF();
    ivPlotter->FIT3D();
    //
    if ( ivPlotter->GetPrsMgr3d().Get() != nullptr )
    {
      snapshot = ivPlotter->GetPrsMgr3d()->DumpPNG();
    }
  }
  
  return snapshot;
}

In this code snippet, we instruct the imperative plotter to initialize the Part Node with the passed geometry instead of creating/updating an object under the "Geometric Set" group. It should be noted that this "part stealing" approach has its inherent deficiencies:

  • This approach cleans up the AAG stored in the Part Node. Such behavior might be non-obvious for a client system if it "only wanted to make a snapshot" without destructing any existing data.
  • The visualization pipeline for a Part is activated bottom-up, requiring the visualization data to be completely recreated, which is not optimal in terms of performance.
The dumped PNG file.

Now, after years passed, I can say that this technique should probably be avoided unless you're actually trying to replicate the existing pipelines in a frame buffer. If what you're up to is just an immediate snapshot of a part's state, then consider the alternative solution presented below.

OpenCascade-based offscreen rendering

Unlike VTK, OpenCascade does not require any specific recompilation mode for offscreen rendering to work out of the box. On Linux systems, OpenCascade's visualization uses software rendering (MESA) and it normally just works. Also, because OpenCascade-based offscreen rendering has nothing to do with the architecture of Analysis Situs, it clearly means that it does not need to respect any architectural constraints. The visualization workflow is entirely shape-based. If there are visualization facets in the shape, then we can render its shading image. If not, then not. Here's how to generate a pixmap using Analysis Situs SDK on top of the OpenCascade's offscreen renderer:

// Pixmap.
Handle(Image_AlienPixMap)
  pixmap = asiAlgo_Utils::Graphics::GeneratePixmap(partSolid, 400, 400);

The logic behind this oneliner is not that trivial though. OpenCascade requires that we create a window for a frame buffer and initialize some visual properties of the object being rendered. What this code actually does is it initializes a viewport and configures the AIS context to prepare the offscreen scene for a dump. You can refer to the sources of asiAlgo_Utils namespace for the implementation details and further settings, such as shape color, line width, etc.

This approach of making snapshots solves the issues with the VTK-based method: it does not lead to remeshing your shape (as long as it already has facets) and it does not penetrate into the project structure of Analysis Situs. It's pretty much like a stateless visual cout for your graphics.

Which one to use?

Definitely, the second one unless you clearly know why you should stick to the first approach. Both methods found their way to industrial software and work nicely in non-GPU environments.

Want to discuss this? Jump in to our forum.