What can cause vtkPolyDataMapper::GetInputAlgorithm() to return null?

I’m developing with C++ and VTK-9.2.6 on ubuntu 20.04.2.

My application displays bathymetry data.

I’ve subclassed vtkAbstractPolyDataReader to GmtGridReader, which reads the bathymetry data from a NetCDF file.

I’ve written a simple test program that reads the bathymetry data with GmtGridData and displays that data.

The program crashes with a segfault/null-pointer exception when it calls vtkRenderer::ResetCamera(), in vtkPolyDataMapper.cxx line 117, as shown by gdb:

117 this->GetInputAlgorithm()->UpdateInformation();

(gdb) print this->GetInputAlgorithm()
$1 = (vtkAlgorithm *) 0x0

And the gdb backtrace:

(gdb) bt
#0 vtkPolyDataMapper::GetBounds (this=0x555556c92120)
at /home/oreilly/VTK-9.2.0.rc2/Rendering/Core/vtkPolyDataMapper.cxx:117
#1 0x00005555558d2b3a in vtkActor::GetBounds (this=0x555556bffdf0)
at /home/oreilly/VTK-9.2.0.rc2/Rendering/Core/vtkActor.cxx:377
#2 0x0000555555948d04 in vtkRenderer::ComputeVisiblePropBounds (
this=0x555556de1550, allBounds=0x7fffffffdc80)
at /home/oreilly/VTK-9.2.0.rc2/Rendering/Core/vtkRenderer.cxx:986
#3 0x000055555594919e in vtkRenderer::ResetCamera (this=0x555556de1550)
at /home/oreilly/VTK-9.2.0.rc2/Rendering/Core/vtkRenderer.cxx:1042
#4 0x00005555558b0295 in main ()

What can cause vtkPolyDataMapper::GetInputAlgorithm() to return null?

Below is my simple test program. Source for GmtGridReader.h and GmtGridReader.cpp is attached. Thanks!

simple test program:
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkNamedColors.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <array>
#include "GmtGridReader.h"

int main(int, char *[]) {
  vtkSmartPointer<vtkNamedColors> colors =
      vtkSmartPointer<vtkNamedColors>::New();

  // Set the background color.
  std::array<unsigned char, 4> bkg{{26, 51, 102, 255}};
  colors->SetColor("BkgColor", bkg.data());

  // Create vtkAbstractPolyDataReader GmtGridReader to load bathymetry grid file
   vtkSmartPointer<mb_system::GmtGridReader> reader =
     vtkSmartPointer<mb_system::GmtGridReader>::New();

   reader->SetFileName("Extravert.grd");
   reader->Update();
   if (reader->GetErrorCode()) {
     std::cout << "Error during reader->Update(): " << reader->GetErrorCode()
               << std::endl;
     return EXIT_FAILURE;
   }
   
  // The mapper is responsible for pushing the geometry into the graphics
  // library. It may also do color mapping, if scalars or other attributes are
  // defined.
  vtkSmartPointer<vtkPolyDataMapper> myMapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
  myMapper->SetInputConnection(reader->GetOutputPort());

  // The actor is a grouping mechanism: besides the geometry (mapper), it
  // also has a property, transformation matrix, and/or texture map.
  // Here we set its color and rotate it around the X and Y axes.
  vtkSmartPointer<vtkActor> myActor = vtkSmartPointer<vtkActor>::New();
  myActor->SetMapper(myMapper);
  myActor->GetProperty()->SetColor(
      colors->GetColor4d("Tomato").GetData());
  myActor->RotateX(30.0);
  myActor->RotateY(-45.0);

  // The renderer generates the image
  // which is then displayed on the render window.
  // It can be thought of as a scene to which the actor is added
  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
  renderer->AddActor(myActor);
  renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());
  // Zoom in a little by accessing the camera and invoking its "Zoom" method.
  std::cout << "call renderer->ResetCamera()" << std::endl;
  renderer->ResetCamera();
  renderer->GetActiveCamera()->Zoom(1.5);

  // The render window is the actual GUI window
  // that appears on the computer screen
  vtkSmartPointer<vtkRenderWindow> renderWindow =
      vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->SetSize(300, 300);
  renderWindow->AddRenderer(renderer);
  renderWindow->SetWindowName("Test");

  // The render window interactor captures mouse events
  // and will perform appropriate camera or actor manipulation
  // depending on the nature of the events.
  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
      vtkSmartPointer<vtkRenderWindowInteractor>::New();
  renderWindowInteractor->SetRenderWindow(renderWindow);

  // This starts the event loop and as a side effect causes an initial render.
  renderWindow->Render();
  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

GmtGridReader.cpp (11.1 KB)
GmtGridReader.h (3.5 KB)

Hello,

Please, post the code of the GmtGridReader class. Properly subclassing VTK classes so they can be used in VTK pipelines is generally not straightforward.

regards,

PC

Thanks @Paulo_Carvalho - please see GmtGridReader class attached (wrong class in my original post!)
This worked under VTK-8.2.0

A clue is that myMapper->GetInputAlgorithm() returns null after this line in main():

` myMapper->SetInputConnection(reader->GetOutputPort());`
  std::cout << "myMapper->GetInputAlgorithm() = " <<
    myMapper->GetInputAlgorithm() << std::endl;

whereas it returns a non-null value in VTK-8.2.0, which works properly. So presumably VTK-9.2.6 doesn’t recognize GmtGridReader as a valid pipeline algorithm?

GmtGridReader.h (3.5 KB)
GmtGridReader.cpp (11.1 KB)

Another clue…
Running the test on two different machines, both running ubuntu 20.04.2, both using VTK-9.2.0.
“Machine A” runs the test app successfully, while the same null-pointer exception occurs on “machine B”.
But this line of code has different results on the two machines:

  vtkSmartPointer<vtkPolyDataMapper> myMapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();

On machine A, myMapper has type vtkOpenGLPolyDataMapper, and the app works properly.
On machine B, myMapper has type vtkPolyDataMapper, and the app exits with a null-pointer exception.

Why does the code on machine A generate a vtkOpenGLPolyDataMapper, and the same app code on machine B generates a vtkPolyDataMapper?
Is this somehow connected with the ‘ccmake’ configuration when building VTK?

Thanks!

Hello,

I’d advise against implementing the constructor yourself. Maybe the protocol has changed in VTK 9 and you need to copy how the boilerplate code in constructors are now. Here’s how I subclassed vtkInteractorStyleTrackballCamera:

Notice I don’t implement a constructor nor a static... New() for my class. That works for both VTK 8 and 9.

take care,

PC

1 Like

Part of VTK code is written on the fly by CMake during configuration. So “the same code” may not be entirely true between two different configurations (even for the same machine/OS/devtool) when it comes to VTK.

1 Like

VTK object factories (that instantiate a specific class when you call New) choose the class depending on the rendering backend, operating system, and graphics system. For example, the mapper may be different on a standard OpenGL configuration than on a headless machine or in a virtual reality renderer.

Check if VTK8 worked properly because it instantiated a different mapper or if the same mapper class was instantiated but it did not crash. You can then continue to find the difference between the two VTK versions and then fix it.

Or, you may be able to avoid the issue by making your rendering configuration a bit less unusual by installing different drivers, x server, etc.