How to use VTK with QT support

I have a vtk pipeline running OK (source + filter + mapper + actor + renderer OK).

Then, I built VTK with Qt support : seems OK + I can run the Examples/GUI/Qt/SimpleView example.

Then, in my vtk pipeline, I’ve just replaced all occurrences of “vtkRenderWindow” with “vtkGenericOpenGLRenderWindow” : compilation OK but run-time crash with following error

2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:68    WARN| Error in cache state for GL_DEPTH_WRITEMASK
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:76    WARN| Error in cache state for GL_COLOR_WRITEMASK
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:97    WARN| Error in cache state for GL_CULL_FACE
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:105   WARN| Error in cache state for GL_MULTISAMPLE
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:120   WARN| Error in cache state for GL_STENCIL_TEST
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:128   WARN| Error in cache state for GL_TEXTURE_CUBE_MAP_SEAMLESS
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:144   WARN| Error in cache state for GL_VIEWPORT
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:152   WARN| Error in cache state for GL_SCISSOR_BOX
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:159   WARN| Error in cache state for GL_CULL_FACE_MODE
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:166   WARN| Error in cache state for GL_ACTIVE_TEXTURE
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:173   WARN| Error in cache state for GL_DEPTH_FUNC
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:180   WARN| Error in cache state for GL_BLEND_SRC_RGB
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:187   WARN| Error in cache state for GL_BLEND_SRC_ALPHA
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:194   WARN| Error in cache state for GL_BLEND_DST_RGB
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:201   WARN| Error in cache state for GL_BLEND_DST_ALPHA
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:208   WARN| Error in cache state for GL_DRAW_FRAMEBUFFER_BINDING
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:215   WARN| Error in cache state for GL_READ_FRAMEBUFFER_BINDING
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:233   WARN| Error in cache state for GL_DRAW_BUFFER got -4183256 expected1026
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:252   WARN| Error in cache state for GL_READ_BUFFER
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:266   WARN| Error in cache state for GL_COLOR_CLEAR_VALUE
2023-03-30 10:25:08.923 (   0.003s) [        FA9FF6C0]     vtkOpenGLState.cxx:274   WARN| at stack loc
0x7f75000962c8 : ??? [(???) ???:-1]
0x7f7500090e6c : vtksys::SystemInformation::GetProgramStack[abi:cxx11](int, int) [(libvtksys-9.2.so.1) ???:-1]
0x7f74ffe19447 : vtkOpenGLState::CheckState() [(libvtkRenderingOpenGL2-9.2.so.1) ???:-1]
0x7f74ffe1ebd2 : vtkOpenGLState::SetEnumState(unsigned int, bool) [(libvtkRenderingOpenGL2-9.2.so.1) ???:-1]
0x7f74ffe1f21b : vtkOpenGLState::vtkglEnable(unsigned int) [(libvtkRenderingOpenGL2-9.2.so.1) ???:-1]
0x7f74ffde8fe4 : vtkOpenGLRenderWindow::Start() [(libvtkRenderingOpenGL2-9.2.so.1) ???:-1]
0x7f74ff7ecfa1 : vtkXRenderWindowInteractor::Initialize() [(libvtkRenderingUI-9.2.so.1) ???:-1]


How to migrate a code from basic VTK pipeline to VTK-with-Qt support?

Hello,

For Qt, you’re better off by using QVTKOpenGLNativeWidget. Here, check this basic yet fully functional Qt widget that has a VTK window: gammaray/imagejockey/widgets at master · PauloCarvalhoRJ/gammaray · GitHub . Look for the three files named ijquick3dviewer.* (a .ui, a .h and a .cpp).

take care,

PC

I have this code that works without Qt:

>> cat testVTKQt.cpp 
#include <iostream>  // cout, cerr
#include <stdexcept> // exception
#include <thread>    // jthread
#include <string>    // string
#include <sstream>   // stringstream
#include <random>    // std::uniform_real_distribution

#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkVertexGlyphFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h" // GetProperty
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"

void updateData(unsigned int const & size,
                vtkNew<vtkPolyData> & data,
                vtkSmartPointer<vtkRenderWindow> & rdrWin,
                bool const updateRender = true) {
  // Create random distribution.
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_real_distribution<float> distrib(-10000., 10000.);

  // Update data with random points.
  vtkNew<vtkPoints> points;
  data->SetPoints(points);
  for (unsigned int i = 0; i < size; i++) {
    data->GetPoints()->InsertNextPoint(distrib(gen), distrib(gen), distrib(gen));
  }

  // Update the scene.
  data->Modified();
  if (updateRender) {
    rdrWin->Render (); // Render an image (lights and cameras are created automatically).
  }
}

void createScene(vtkNew<vtkPolyData> & data,
                 vtkSmartPointer<vtkRenderWindow> & rdrWin) {
  // Create a filter.
  vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
  filter->SetInputData(data);

  // Create a mapper.
  vtkSmartPointer<vtkPolyDataMapper> map = vtkSmartPointer<vtkPolyDataMapper>::New();
  map->SetInputConnection(filter->GetOutputPort()); // Map to graphics library.

  // Create an actor.
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(map);

  // Create a renderer and a render window. Renderers and Windows represent the end of the VTK pipeline, which users actually see on the screen.
  vtkSmartPointer<vtkRenderer> rdr = vtkSmartPointer<vtkRenderer>::New();
  rdrWin->AddRenderer(rdr);
  vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
  rdrInt->SetRenderWindow(rdrWin);
  rdrInt->Initialize();

  // Define the scene to render.
  actor->GetProperty()->SetColor(0, 0, 1); // Set sphere color to blue (RGB).
  rdr->AddActor(actor);                    // Add the actor to the scene.
  rdr->SetBackground(1, 1, 1);             // Background color white.

  // Render.
  rdrWin->Render (); // Render an image (lights and cameras are created automatically).
  rdrInt->Start ();  // Hold window and watches for events (keypress, mouse, ...) in the vtkRenderWindow.
}

int main () {
  int rc = 1;

  try {
    // Create point cloud.
    vtkSmartPointer<vtkRenderWindow> rdrWin = vtkSmartPointer<vtkRenderWindow>::New(); // Window to render into.
    vtkNew<vtkPolyData> data;
    updateData(100, data, rdrWin, false); // Do NOT render until the thread has not started and set up the scene.
    std::jthread visu(createScene, std::ref(data), std::ref(rdrWin));

    // Modify the scene.
    std::cout << "Type a number (integer) as point cloud size..." << std::endl;
    while (true) {
      // Getting user command.
      std::string line;
      std::getline(std::cin, line);

      // Getting point cloud size.
      std::stringstream str;
      str << line;
      unsigned int size = 0;
      str >> size;
      if (!str) {
        std::cout << "Bad number (not an integer): " << line << std::endl;
        continue;
      }

      // Update point cloud.
      std::cout << "Point cloud size: " << size << std::endl;
      updateData(size, data, rdrWin);
    };
    rc = 0;
  }
  catch(std::exception & e) {
    rc = 1;
    cerr << "ERROR - " << e.what() << endl;
  }

  return rc;
}

Now, I have compiled VTK from source with Qt support, and I have tested that <VTK_ROOT>/Examples/GUI/Qt/SimpleView example works OK.

But, when I try to include this VTK code in Qt:


>> git diff
diff --git a/testVTKQt.cpp b/testVTKQt.cpp
index 7e17c1a..ac6cb0a 100644
--- a/testVTKQt.cpp
+++ b/testVTKQt.cpp
@@ -5,6 +5,13 @@
 #include <sstream>   // stringstream
 #include <random>    // std::uniform_real_distribution
 
+//----------Since we're not building with CMake, we need to init the VTK modules------------------
+//--------------linking with the VTK libraries is often not enough--------------------------------
+#include <vtkAutoInit.h>
+VTK_MODULE_INIT(vtkRenderingOpenGL2) // VTK was built with vtkRenderingOpenGL2
+VTK_MODULE_INIT(vtkInteractionStyle)
+VTK_MODULE_INIT(vtkRenderingFreeType)
+// VTK
 #include "vtkNew.h"
 #include "vtkSmartPointer.h"
 #include "vtkPoints.h"
@@ -14,12 +21,17 @@
 #include "vtkProperty.h" // GetProperty
 #include "vtkActor.h"
 #include "vtkRenderer.h"
-#include "vtkRenderWindow.h"
-#include "vtkRenderWindowInteractor.h"
+#include "vtkGenericOpenGLRenderWindow.h"
+//#include "vtkRenderWindowInteractor.h"
+
+// Qt
+#include <QtGui/QSurfaceFormat>
+#include <QtWidgets/QApplication>
+#include "QVTKOpenGLNativeWidget.h"
 
 void updateData(unsigned int const & size,
                 vtkNew<vtkPolyData> & data,
-                vtkSmartPointer<vtkRenderWindow> & rdrWin,
+                vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin,
                 bool const updateRender = true) {
   // Create random distribution.
   std::random_device rd;
@@ -40,8 +52,9 @@ void updateData(unsigned int const & size,
   }
 }
 
-void createScene(vtkNew<vtkPolyData> & data,
-                 vtkSmartPointer<vtkRenderWindow> & rdrWin) {
+void createScene(QVTKOpenGLNativeWidget & wdg,
+                 vtkNew<vtkPolyData> & data,
+                 vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin) {
   // Create a filter.
   vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
   filter->SetInputData(data);
@@ -55,11 +68,12 @@ void createScene(vtkNew<vtkPolyData> & data,
   actor->SetMapper(map);
 
   // Create a renderer and a render window. Renderers and Windows represent the end of the VTK pipeline, which users actually see on the screen.
+  wdg.setRenderWindow(rdrWin);
   vtkSmartPointer<vtkRenderer> rdr = vtkSmartPointer<vtkRenderer>::New();
-  rdrWin->AddRenderer(rdr);
-  vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
-  rdrInt->SetRenderWindow(rdrWin);
-  rdrInt->Initialize();
+  wdg.renderWindow()->AddRenderer(rdr);
+  //vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
+  //rdrInt->SetRenderWindow(rdrWin);
+  //rdrInt->Initialize();
 
   // Define the scene to render.
   actor->GetProperty()->SetColor(0, 0, 1); // Set sphere color to blue (RGB).
@@ -68,18 +82,32 @@ void createScene(vtkNew<vtkPolyData> & data,
 
   // Render.
   rdrWin->Render (); // Render an image (lights and cameras are created automatically).
-  rdrInt->Start ();  // Hold window and watches for events (keypress, mouse, ...) in the vtkRenderWindow.
+  //rdrInt->Start ();  // Hold window and watches for events (keypress, mouse, ...).
+}
+
+void createApplication(int & argc, char** argv,
+                       vtkNew<vtkPolyData> & data,
+                       vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin) {
+  // Needed to ensure appropriate OpenGL context is created for VTK rendering.
+  QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
+
+  // Create Qt application.
+  QApplication app(argc, argv);
+  //QVTKRenderWidget wdg;
+  QVTKOpenGLNativeWidget wdg;
+  createScene(wdg, data, rdrWin);
+  app.exec();
 }
 
-int main () {
+int main (int argc, char** argv) {
   int rc = 1;
 
   try {
     // Create point cloud.
-    vtkSmartPointer<vtkRenderWindow> rdrWin = vtkSmartPointer<vtkRenderWindow>::New(); // Window to render into.
+    vtkSmartPointer<vtkGenericOpenGLRenderWindow> rdrWin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New(); // Window to render into.
     vtkNew<vtkPolyData> data;
     updateData(100, data, rdrWin, false); // Do NOT render until the thread has not started and set up the scene.
-    std::jthread visu(createScene, std::ref(data), std::ref(rdrWin));
+    std::jthread visu(createApplication, std::ref(argc), std::ref(argv), std::ref(data), std::ref(rdrWin));
 
     // Modify the scene.
     std::cout << "Type a number (integer) as point cloud size..." << std::endl;


I have :

  1. replaced vtkRenderWindow with vtkGenericOpenGLRenderWindow
  2. commented vtkRenderWindowInteractor taht seems to make Qt crash
  3. created QVTKOpenGLNativeWidget (same problem with QVTKRenderWidget) and QApplication

… But, get no window at run time:

./testVTKQt

does not open / render any window ?!..

did i miss something ?

any help is appreciated!

Please, post the code without diff markings. It’s really confusing.

Sure!

So, restarting from scratch, I have this code that works without Qt (here the idea is to do stuffs in main thread handling parameters [size], and, to delegate the whole visualization to a dedicated thread [jthread]):

>> cat CMakeLists.txt 
cmake_minimum_required (VERSION 3.20)

# Define project
project(mapView)

# Find external library
find_package(VTK REQUIRED)

# Handle compile options.
if (CMAKE_COMPILER_IS_GNUCXX)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -Wall -Wextra -Werror")
endif()

# Define binary
add_executable(mapView mapView.cpp)
target_include_directories(mapView PRIVATE "${VTK_INCLUDE_DIRS}")
target_link_libraries(mapView PRIVATE "${VTK_LIBRARIES}")
set_property(TARGET mapView PROPERTY CXX_STANDARD 20)

# Print summary.
message(STATUS "Summary:")
message(STATUS "  CMAKE_C_FLAGS=${CMAKE_C_FLAGS}")
message(STATUS "  CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")


>> cat mapView.cpp 
#include <iostream>  // cout, cerr
#include <stdexcept> // exception
#include <thread>    // jthread
#include <string>    // string
#include <sstream>   // stringstream
#include <random>    // std::uniform_real_distribution

#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkVertexGlyphFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h" // GetProperty
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"

void updateData(unsigned int const & size,
                vtkNew<vtkPolyData> & data,
                vtkSmartPointer<vtkRenderWindow> & rdrWin,
                bool const updateRender = true) {
  // Create random distribution.
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_real_distribution<float> distrib(-10000., 10000.);

  // Update data with random points.
  vtkNew<vtkPoints> points;
  data->SetPoints(points);
  for (unsigned int i = 0; i < size; i++) {
    data->GetPoints()->InsertNextPoint(distrib(gen), distrib(gen), distrib(gen));
  }

  // Update the scene.
  data->Modified();
  if (updateRender) {
    rdrWin->Render (); // Render an image (lights and cameras are created automatically).
  }
}

void createScene(vtkNew<vtkPolyData> & data,
                 vtkSmartPointer<vtkRenderWindow> & rdrWin) {
  // Create a filter.
  vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
  filter->SetInputData(data);

  // Create a mapper.
  vtkSmartPointer<vtkPolyDataMapper> map = vtkSmartPointer<vtkPolyDataMapper>::New();
  map->SetInputConnection(filter->GetOutputPort()); // Map to graphics library.

  // Create an actor.
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(map);

  // Create a renderer and a render window. Renderers and Windows represent the end of the VTK pipeline, which users actually see on the screen.
  vtkSmartPointer<vtkRenderer> rdr = vtkSmartPointer<vtkRenderer>::New();
  rdrWin->AddRenderer(rdr);
  vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
  rdrInt->SetRenderWindow(rdrWin);
  rdrInt->Initialize();

  // Define the scene to render.
  actor->GetProperty()->SetColor(0, 0, 1); // Set sphere color to blue (RGB).
  rdr->AddActor(actor);                    // Add the actor to the scene.
  rdr->SetBackground(1, 1, 1);             // Background color white.

  // Render.
  rdrWin->Render (); // Render an image (lights and cameras are created automatically).
  rdrInt->Start ();  // Hold window and watches for events (keypress, mouse, ...) in the vtkRenderWindow.
}

int main () {
  int rc = 1;

  try {
    // Create point cloud.
    vtkSmartPointer<vtkRenderWindow> rdrWin = vtkSmartPointer<vtkRenderWindow>::New(); // Window to render into.
    vtkNew<vtkPolyData> data;
    updateData(100, data, rdrWin, false); // Do NOT render until the thread has not started and set up the scene.
    std::jthread visu(createScene, std::ref(data), std::ref(rdrWin));

    // Modify the scene.
    std::cout << "Type a number (integer) as point cloud size..." << std::endl;
    while (true) {
      // Getting user command.
      std::string line;
      std::getline(std::cin, line);

      // Getting point cloud size.
      std::stringstream str;
      str << line;
      unsigned int size = 0;
      str >> size;
      if (!str) {
        std::cout << "Bad number (not an integer): " << line << std::endl;
        continue;
      }

      // Update point cloud.
      std::cout << "Point cloud size: " << size << std::endl;
      updateData(size, data, rdrWin);
    };
    rc = 0;
  }
  catch(std::exception & e) {
    rc = 1;
    cerr << "ERROR - " << e.what() << endl;
  }

  return rc;
}


Then, I have compiled VTK from source with Qt support, and I have tested that <VTK_ROOT>/Examples/GUI/Qt/SimpleView example works OK.

When I try to include this VTK code in Qt (here the idea is to do the “same thing but embedding the VTK viewer in a Qt GUI”)):


>> cat CMakeLists.txt 
cmake_minimum_required (VERSION 3.20)

# Define project
project(mapView)

# Find VTK.
find_package(VTK REQUIRED)

# Find Qt.
find_package(Qt6 COMPONENTS Widgets Gui REQUIRED)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

# Handle compile options.
if (CMAKE_COMPILER_IS_GNUCXX)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -Wall -Wextra -Werror")
endif()

# Define binary
add_executable(mapView mapView.cpp)
target_include_directories(mapView PRIVATE "${VTK_INCLUDE_DIRS}" Qt6::Gui Qt6::Widgets)
target_link_libraries(mapView PRIVATE "${VTK_LIBRARIES}" Qt6::Gui Qt6::Widgets)
set_property(TARGET mapView PROPERTY CXX_STANDARD 20)

# Print summary.
message(STATUS "Summary:")
message(STATUS "  CMAKE_C_FLAGS=${CMAKE_C_FLAGS}")
message(STATUS "  CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")


>> cat mapView.cpp 
#include <iostream>  // cout, cerr
#include <stdexcept> // exception
#include <thread>    // jthread
#include <string>    // string
#include <sstream>   // stringstream
#include <random>    // std::uniform_real_distribution

//----------Since we're not building with CMake, we need to init the VTK modules------------------
//--------------linking with the VTK libraries is often not enough--------------------------------
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2) // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
// VTK
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkVertexGlyphFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h" // GetProperty
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkGenericOpenGLRenderWindow.h"
//#include "vtkRenderWindowInteractor.h"

// Qt
#include <QtGui/QSurfaceFormat>
#include <QtWidgets/QApplication>
#include "QVTKOpenGLNativeWidget.h"

void updateData(unsigned int const & size,
                vtkNew<vtkPolyData> & data,
                vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin,
                bool const updateRender = true) {
  // Create random distribution.
  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_real_distribution<float> distrib(-10000., 10000.);

  // Update data with random points.
  vtkNew<vtkPoints> points;
  data->SetPoints(points);
  for (unsigned int i = 0; i < size; i++) {
    data->GetPoints()->InsertNextPoint(distrib(gen), distrib(gen), distrib(gen));
  }

  // Update the scene.
  data->Modified();
  if (updateRender) {
    rdrWin->Render (); // Render an image (lights and cameras are created automatically).
  }
}

void createScene(QVTKOpenGLNativeWidget & wdg,
                 vtkNew<vtkPolyData> & data,
                 vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin) {
  // Create a filter.
  vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
  filter->SetInputData(data);

  // Create a mapper.
  vtkSmartPointer<vtkPolyDataMapper> map = vtkSmartPointer<vtkPolyDataMapper>::New();
  map->SetInputConnection(filter->GetOutputPort()); // Map to graphics library.

  // Create an actor.
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(map);

  // Create a renderer and a render window. Renderers and Windows represent the end of the VTK pipeline, which users actually see on the screen.
  wdg.setRenderWindow(rdrWin);
  vtkSmartPointer<vtkRenderer> rdr = vtkSmartPointer<vtkRenderer>::New();
  wdg.renderWindow()->AddRenderer(rdr);
  //vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
  //rdrInt->SetRenderWindow(rdrWin);
  //rdrInt->Initialize();

  // Define the scene to render.
  actor->GetProperty()->SetColor(0, 0, 1); // Set sphere color to blue (RGB).
  rdr->AddActor(actor);                    // Add the actor to the scene.
  rdr->SetBackground(1, 1, 1);             // Background color white.

  // Render.
  rdrWin->Render (); // Render an image (lights and cameras are created automatically).
  //rdrInt->Start ();  // Hold window and watches for events (keypress, mouse, ...).
}

void createApplication(int & argc, char** argv,
                       vtkNew<vtkPolyData> & data,
                       vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin) {
  // Needed to ensure appropriate OpenGL context is created for VTK rendering.
  QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());

  // Create Qt application.
  QApplication app(argc, argv);
  //QVTKRenderWidget wdg;
  QVTKOpenGLNativeWidget wdg;
  createScene(wdg, data, rdrWin);
  app.exec();
}

int main (int argc, char** argv) {
  int rc = 1;

  try {
    // Create point cloud.
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> rdrWin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New(); // Window to render into.
    vtkNew<vtkPolyData> data;
    updateData(100, data, rdrWin, false); // Do NOT render until the thread has not started and set up the scene.
    std::jthread visu(createApplication, std::ref(argc), std::ref(argv), std::ref(data), std::ref(rdrWin));

    // Modify the scene.
    std::cout << "Type a number (integer) as point cloud size..." << std::endl;
    while (true) {
      // Getting user command.
      std::string line;
      std::getline(std::cin, line);

      // Getting point cloud size.
      std::stringstream str;
      str << line;
      unsigned int size = 0;
      str >> size;
      if (!str) {
        std::cout << "Bad number (not an integer): " << line << std::endl;
        continue;
      }

      // Update point cloud.
      std::cout << "Point cloud size: " << size << std::endl;
      updateData(size, data, rdrWin);
    };
    rc = 0;
  }
  catch(std::exception & e) {
    rc = 1;
    cerr << "ERROR - " << e.what() << endl;
  }

  return rc;
}


In the above code, basically, I have :

  • replaced vtkRenderWindow with vtkGenericOpenGLRenderWindow
  • commented vtkRenderWindowInteractor that seems to make Qt crash
  • created a QApplication and a QVTKOpenGLNativeWidget (same problem with QVTKRenderWidget)

But, get no window at run time:

./mapView

Does not open / render any window ?!..

Man!.. Just realized that wdg.show() was missing?! :slight_smile: Now when I run mapView the rendered appears!

But, when I try to change the scene (inputting a number in the main thread), I get:

>> ./mapView
Type a number (integer) as point cloud size...
1000
Point cloud size: 1000
Cannot make QOpenGLContext current in a different thread
Aborted

Hello,

I believe you don’t need these since you’re building with CMake:

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2) // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)

best,

PC

Part of VTK objects are in main()'s thread and part is in another thread. I’d advice against doing that. Also, That’s an unusual way to start a Qt application. See the main() of one of my projects:

#include <QApplication>

#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //You can process argc and argv here or elsewhere 
    //via QCoreApplication::arguments()

    QApplication::setOrganizationName("myUberCompany");
    QApplication::setOrganizationDomain("mySuperDuperApp.myUberCompany.com");
    QApplication::setApplicationName("mySuperDuperApp");
    MainWindow w;
    w.show();

    return a.exec();
}

This way you have Qt’s event loop running in the same thread of main().

take care,

PC

Yes, you are right!

1 Like

Correct! Works now

1 Like