Logs
Consultez les logs.
OK
Liste des données
Consultez la liste des données.
OK
Loading...
Formulaire
Saisissez vos données.
Enregistrer
Annuler

Visualisation 3D avec VTK

Vues
155

Ce document est un recueil de recettes pratiques pour la mise en oeuvre d'un environnement de rendu 3D avec VTK en C++. Ce document présente la conception d'un système de visualisation 3D en C++, Qt, CMake avec VTK.

image.png



Notes sur la démo


Notre système permettra de visualiser des données 3D au format « VTK ».

 


Notes techniques


Notre système de visualisation 3D sera basé sur les modules VTK, Qt et OpenGL. Le module VTK fournira des classes qui prendront en charge de manière transparente les couches Qt et OpenGL afin de faciliter la mise en oeuvre du processus de rendu 3D.


VTK


VTK (Visualization Tool Kit) est une librairie C++ sophistiquée pour l'infographie 3D, le traitement d'images, la modélisation, le rendu volumique et la visualisation scientifique. VTK est une extension des fonctionnalités OpenGL pour faciliter le rendu de scène 3D.

VTK = OpenGL + Fonctionnalités

Le module VTK s'appuie sur la couche OpenGL pour exploiter la puissance des processeurs graphiques GPU afin de bénéficier de l'accélération matérielle lors du rendu 3D.

QSurfaceFormat


QSurfaceFormat (Format de surface Qt pour OpenGL) est un ensemble de paramètres prédéfinis pour le rendu OpenGL. Il définit un certain nombre de paramètres OpenGL par défaut tels que, le profil, la version, la taille des tampons des couleurs RGBA, la taille des tampons de profondeur, le nombre d'échantillons par pixel.

QVTKOpenGLNativeWidget


QVTKOpenGLNativeWidget (Qt VTK OpenGL Native Widget) est un widget Qt pour le rendu OpenGL de données au format « VTK ». Il étend les fonctionnalités du widget Qt OpenGL « QOpenGLWidget » pour le rendu de données au format « VTK ».

QVTKOpenGLNativeWidget = QOpenGLWidget + Fonctionnalités
QOpenGLWidget = Qt + OpenGL  + Fonctionnalités

QVTKOpenGLNativeWidget::defaultFormat (QSurfaceFormat pour VTK) est un ensemble de paramètres OpenGL prédéfinis pour le rendu de données au format « VTK ».

vtkCamera


vtkCamera est une caméra virtuelle pour le rendu 3D de données « VTK ». vtkCamera permet de positionner et d'orienter le point de vue et le point focal de la caméra. vtkCamera permet de paramétrer la caméra selon 3 critères :

(1) La direction de la vue vers le haut de la caméra, par défaut, (0, 1, 0).
(2) La position de la caméra dans le repère du monde réel, par exemple, (0, 0, 10).
(3) Le point focal de la caméra dans le repère du monde réel, par exemple, (0, 0, 0).

image.png

vtkRenderer


vtkRenderer est un moteur de rendu 3D de données « VTK ». vtkRenderer contrôle le processus de rendu des objets dans le but de convertir la géométrie, l'éclairage et la vue de la caméra en une image. vtkRenderer effectue aussi la transformation des coordonnées entre les coordonnées du monde réel, les coordonnées de la vue (le système de coordonnées de rendu graphique) et les coordonnées d'affichage (les coordonnées réelles de l'écran). vtkRenderer peut également contrôler certaines fonctionnalités de rendu avancées, tel que l'éclairage bilatéral.

vtkActor


vtkActor représente une entité dans une scène de rendu de données « VTK ». vtkActor représente un objet qu'on veut visualiser dans la fenêtre de rendu de données « VTK ».  


Notes sur le développement


Notre système de visualisation 3D, sera développé en langage C++ sous l'éditeur VSCode, utilisera l'outil CMake pour construire le projet, utilisera un fichier ressource QRC pour alimenter les icônes de l'application, utilisera l'outil Qt Widgets Designer pour concevoir l'interface utilisateur de la fenêtre principale de l'application, utilisera les feuilles de style QSS pour mettre en forme les widgets de l'application.


Configuration de l'éditeur VSCode


// .vscode/settings.json
...
{
    "cmake.environment": {
        "PATH": "C:/tools/Qt/6.9.0/msvc2022_64/bin;C:/Program Files (x86)/VTK/bin",
    },
}
...

Configuration de la construction du projet


// CMakeLists.txt
...
cmake_minimum_required(VERSION 3.10.0)
project(rdvvtk VERSION 0.1.0 LANGUAGES C CXX)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
set(CMAKE_INCLUDE_CURRENT_DIR ON)

find_package(Qt6 REQUIRED COMPONENTS
    Core
    Gui
    Widgets
    OpenGLWidgets
)

find_package(VTK 9.5 REQUIRED COMPONENTS
    GUISupportQt
    IOLegacy
)

include_directories(${CMAKE_HOME_DIRECTORY})

set(SRC_FILES
    main.cpp
    MainWindow.hpp
    MainWindow.cpp
    SceneWidget.hpp
    SceneWidget.cpp
)

qt_wrap_ui(UI_FILES
    MainWindow.ui
)

set(RCC_FILES
    resources.qrc
)

qt_add_executable(${PROJECT_NAME} WIN32
    ${SRC_FILES}
    ${UI_FILES}
    ${RCC_FILES}
)

target_link_libraries(${PROJECT_NAME} PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Widgets
    Qt6::OpenGLWidgets
    VTK::GUISupportQt
    VTK::IOLegacy
)
...

Configuration des ressources du projet


// resources.qrc
...
<RCC>
    <qresource prefix="/img">
        <file alias="app-logo.png">res/img/app-logo.png</file>
        <file alias="open_file.png">res/img/open_file.png</file>
        <file alias="zoom_to.png">res/img/zoom_to.png</file>
        <file alias="quit.png">res/img/quit.png</file>
        <file alias="about.png">res/img/about.png</file>
    </qresource>
</RCC>
...

Chargement de la fenêtre principale


// main.cpp
int main(int argc, char *argv[])
{
    qDebug() << "(rdvvtk) Demarrage de l'application";
    QSurfaceFormat::setDefaultFormat(
    QVTKOpenGLNativeWidget::defaultFormat());

    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Conception de la fenêtre principale


// MainWindow.ui
image.png

Ouverture d'un fichier au format VTK


// MainWindow.cpp
...
void MainWindow::showOpenFileDialog()
{
    QString fileName = QFileDialog::getOpenFileName(
        this, tr("Open file"), "",
        "VTK Files (*.vtk)");

    // Open file
    QFile file(fileName);
    file.open(QIODevice::ReadOnly);

    // Return on Cancel
    if (!file.exists())
        return;

    openFile(fileName);
}
...

Chargement d'un fichier au format VTK


// MainWindow.cpp
...
void MainWindow::openFile(const QString &fileName)
{
    ui->sceneWidget->removeDataSet();

    // Create reader
    vtkSmartPointer<vtkDataSetReader> reader = 
    vtkSmartPointer<vtkDataSetReader>::New();
    reader->SetFileName(fileName.toStdString().c_str());

    // Read the file
    reader->Update();

    // Add data set to 3D view
    vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
    if (dataSet != nullptr)
    {
        ui->sceneWidget->addDataSet(reader->GetOutput());
    }
}
...

Visualisation 3D des données au format VTK


// SceneWidget.cpp
...
void SceneWidget::addDataSet(vtkSmartPointer<vtkDataSet> dataSet)
{
    // Actor
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();

    // Mapper
    vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
    mapper->SetInputData(dataSet);
    actor->SetMapper(mapper);

    m_renderer->AddActor(actor);
    m_renderer->ResetCamera(dataSet->GetBounds());

    renderWindow()->Render();
}
...

Réinitialisation automatique du rendu 3D VTK


// SceneWidget.cpp
...
void SceneWidget::zoomToExtent()
{
    vtkSmartPointer<vtkActor> actor = m_renderer->GetActors()->GetLastActor();
    if (actor != nullptr)
    {
        m_renderer->ResetCamera(actor->GetBounds());
    }

    renderWindow()->Render();
}
...

Suppression du dernier acteur VTK


// SceneWidget.cpp
...
void SceneWidget::removeDataSet()
{
    vtkActor *actor = m_renderer->GetActors()->GetLastActor();
    if (actor != nullptr)
    {
        m_renderer->RemoveActor(actor);
    }

    renderWindow()->Render();
}
...

Initialisation de la caméra VTK


// SceneWidget.cpp
...
SceneWidget::SceneWidget(QWidget *parent)
    : QVTKOpenGLNativeWidget(parent)
{
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> window =
        vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    setRenderWindow(window.Get());

    // Camera
    vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
    camera->SetViewUp(0, 1, 0);
    camera->SetPosition(0, 0, 10);
    camera->SetFocalPoint(0, 0, 0);

    // Renderer
    m_renderer = vtkSmartPointer<vtkRenderer>::New();
    m_renderer->SetActiveCamera(camera);
    m_renderer->SetBackground(0.1, 0.1, 0.1);
    renderWindow()->AddRenderer(m_renderer);
}
...