QVTKOpenGLWidget: simple animation does not work in a repository version of VTK.

Hello everyone,

A simple animation like “rotating cone” (VTK\Examples\Tutorial\Step1\Cxx\Cone.cxx)
does not properly work in a recent repository version of VTK if I use QVTKOpenGLWidget,
while it properly works in VTK 8.2.0.

In the code attached below, I tried to rotate a cone by 180 degrees, repeating

ren->GetActiveCamera()->Azimuth(1);

and

#if VTK_MINOR_VERSION < 90
        qvtk->GetRenderWindow()->Render();
#else
        qvtk->renderWindow()->Render();
#endif

In VTK 8.2.0, it works well, but in the recent repository version (Version 8.90.0?), only the first and the last images are displayed. (the intermediate states between 0 and 180 degrees are not displayed.)

Some additional procedures are required in the Version 8.90.0 in order to achieve an expected result like VTK 8.2.0?

I appreciate any help.

Thanks in advance and best regards.


cone_rot_main.cpp cone_rot_main.cpp (177 Bytes)

#include "cone_rot.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
    return a.exec();
}

cone_rot.cpp cone_rot.cpp (1.7 KB)

#include <vtkSmartPointer.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkCamera.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
 
#include <QPushButton>
#include <QVBoxLayout>
#include <QVTKOpenGLWidget.h>
 
#include "cone_rot.h"
 
Widget::Widget(QWidget *parent) : QWidget(parent)
{
    // Push button
    push_button = new QPushButton;
    push_button->setText("Rotate");
 
    // QVTK
    qvtk = new QVTKOpenGLWidget;
 
    // Layout
    layout = new QVBoxLayout;
    layout->addWidget(push_button);
    layout->addWidget(qvtk);
    setLayout(layout);
    resize(400, 300);
 
    // Signal & slot
    connect(push_button, SIGNAL(clicked()), this, SLOT(rotate_cone()));
 
    cone = vtkSmartPointer<vtkConeSource>::New();
    actor = vtkSmartPointer<vtkActor>::New();
    ren = vtkSmartPointer<vtkRenderer>::New();
 
    auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    auto renwin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
 
    mapper->SetInputConnection(cone->GetOutputPort());
    actor->SetMapper(mapper);
    ren->AddActor(actor);
    renwin->AddRenderer(ren);
 
#if VTK_MINOR_VERSION < 90
    qvtk->SetRenderWindow(renwin);
#else
    qvtk->setRenderWindow(renwin);
#endif
}
 
Widget::~Widget()
{
    delete push_button;
    delete qvtk;
    delete layout;
}
 
void Widget::rotate_cone() const
{
    for (auto i = 0; i < 180; ++i) {
#if VTK_MINOR_VERSION < 90
        qvtk->GetRenderWindow()->Render();
#else
        qvtk->renderWindow()->Render();
#endif
        ren->GetActiveCamera()->Azimuth(1);
    }
}

cone_rot.h cone_rot.h (610 Bytes)

#pragma once
 
#include <vtkSmartPointer.h>
#include <vtkConeSource.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
 
#include <QWidget>
 
class QPushButton;
class QVTKOpenGLWidget;
class QVBoxLayout;
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
 
private slots:
    void rotate_cone() const;
 
private:
    QPushButton* push_button;
    QVTKOpenGLWidget* qvtk;
    QVBoxLayout* layout;
 
    vtkSmartPointer<vtkConeSource> cone;
    vtkSmartPointer<vtkActor> actor;
    vtkSmartPointer<vtkRenderer> ren;
};

CMakeLists.txt CMakeLists.txt (607 Bytes)

cmake_minimum_required(VERSION 3.10)

# Target
set(TARGET_NAME cone_rot)
project(${TARGET_NAME})

# VTK
find_package(VTK REQUIRED)
message (STATUS "VTK_VERSION: ${VTK_VERSION}")
if (VTK_VERSION VERSION_LESS "8.90.0")
  include(${VTK_USE_FILE})
endif()

# Qt5
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

# Target
set( Srcs ${TARGET_NAME}_main.cpp ${TARGET_NAME}.cpp ${TARGET_NAME}.h)

find_package(Qt5 COMPONENTS Widgets REQUIRED)

add_executable(${TARGET_NAME} ${Srcs})

# Qt5 libraires
target_link_libraries(${TARGET_NAME} Qt5::Widgets)

target_link_libraries(${TARGET_NAME} ${VTK_LIBRARIES})

You either need to use a Qt timer (instead of the for loop) or call processEvents in the for loop to allow any widget updates to happen (to give a chance to the application to process paint events).

Thank you very much for the prompt and perfect solution!

Simply inserting QCoreApplication::processEvents() did the trick.

    for (auto i = 0; i < 180; ++i) {
        qvtk->renderWindow()->Render();
        ren->GetActiveCamera()->Azimuth(1);
        QCoreApplication::processEvents();
    }