云计算百科
云计算领域专业知识百科平台

QT中使用QVTKOpenGLNativeWidget显示三维图形(VTK9.x以上版本)

1.VTK 版本演进与qt插件支持变化

  • VTK ≤ 7.x:官方提供 QVTKWidget 插件,需手动将 QVTKWidgetPlugin.dll/lib 放入 Qt Designer 的插件目录 1。
  • VTK 8.2 之前:推荐使用 QVTKOpenGLWidget 。
  • VTK 8.2 及之后:引入 QVTKOpenGLNativeWidget,替代旧版插件 。
  • VTK 9.0+:彻底移除 QVTKWidget,仅保留 QVTKOpenGLNativeWidget不再提供 Qt Designer 插件 。
  • 使用QVTKOpenGLNativeWidget的更加方便,无需在Qt Designer插件再添加相应的插件目录
  • 此外无需在qt designer中在将widget提升为QVTKOpenGLNativeeWidget,
  • 以上两种方式都不便于代码的移植
  • 使用QVTKOpenGLNativeWidget可以直接将vtk显示的窗口初始化后,直接通过
  • qt addwidget接口添加到显示界面即可。

2.QVTKOpenGLNativeWidget使用方法

首先通过cmake配置所示包含文件以及链接库

包含文件

链接库

链接库主要文件如下

E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkGUISupportQt-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkInteractionWidgets-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkRenderingOpenGL2-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkRenderingHyperTreeGrid-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkRenderingUI-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkglew-9.3.lib opengl32.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkRenderingContext2D-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkIOImage-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkImagingCore-9.3.lib C:\\Qt\\5.15.2\\msvc2019_64\\lib\\Qt5OpenGL.lib C:\\Qt\\5.15.2\\msvc2019_64\\lib\\Qt5Widgets.lib C:\\Qt\\5.15.2\\msvc2019_64\\lib\\Qt5Gui.lib C:\\Qt\\5.15.2\\msvc2019_64\\lib\\Qt5Core.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkRenderingCore-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkFiltersSources-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkFiltersGeneral-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkFiltersCore-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkCommonExecutionModel-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkCommonDataModel-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkCommonTransforms-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkCommonMisc-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkCommonMath-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkCommonCore-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtksys-9.3.lib ws2_32.lib dbghelp.lib psapi.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtktoken-9.3.lib E:\\NativeThirdParty\\VTK_9_3\\lib\\vtkkissfft-9.3.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib

预编译定义

WIN32 _WINDOWS NDEBUG kiss_fft_scalar=double KISSFFT_DLL_IMPORT=1 QT_OPENGL_LIB QT_WIDGETS_LIB QT_GUI_LIB QT_CORE_LIB QT_NO_DEBUG CMAKE_INTDIR="RelWithDebInfo"

c++ 代码

// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#include <QVTKOpenGLNativeWidget.h>
#include <vtkActor.h>
#include <vtkDataSetMapper.h>
#include <vtkDoubleArray.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>

#include <QApplication>
#include <QDockWidget>
#include <QGridLayout>
#include <QLabel>
#include <QMainWindow>
#include <QPointer>
#include <QPushButton>
#include <QVBoxLayout>

#include <cmath>
#include <cstdlib>
#include <random>

namespace
{
/**
* Deform the sphere source using a random amplitude and modes and render it in
* the window
*
* @param sphere the original sphere source
* @param mapper the mapper for the scene
* @param window the window to render to
* @param randEng the random number generator engine
*/
void Randomize(vtkSphereSource* sphere, vtkMapper* mapper, vtkGenericOpenGLRenderWindow* window,
std::mt19937& randEng);
} // namespace

int main(int argc, char* argv[])
{
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());

QApplication app(argc, argv);

// main window
QMainWindow mainWindow;
mainWindow.resize(1200, 900);

// control area
QDockWidget controlDock;
mainWindow.addDockWidget(Qt::LeftDockWidgetArea, &controlDock);

QLabel controlDockTitle("Control Dock");
controlDockTitle.setMargin(20);
controlDock.setTitleBarWidget(&controlDockTitle);

QPointer<QVBoxLayout> dockLayout = new QVBoxLayout();
QWidget layoutContainer;
layoutContainer.setLayout(dockLayout);
controlDock.setWidget(&layoutContainer);

QPushButton randomizeButton;
randomizeButton.setText("Randomize");
dockLayout->addWidget(&randomizeButton);

// render area
QPointer<QVTKOpenGLNativeWidget> vtkRenderWidget = new QVTKOpenGLNativeWidget();g

//将生成的QVTKOpenGLNativeWidget设置为mainwindow主窗口部分
mainWindow.setCentralWidget(vtkRenderWidget);
// VTK part
vtkNew<vtkGenericOpenGLRenderWindow> window;
vtkRenderWidget->setRenderWindow(window.Get());

vtkNew<vtkSphereSource> sphere;
sphere->SetRadius(1.0);
sphere->SetThetaResolution(100);
sphere->SetPhiResolution(100);

vtkNew<vtkDataSetMapper> mapper;
mapper->SetInputConnection(sphere->GetOutputPort());

vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetEdgeVisibility(true);
actor->GetProperty()->SetRepresentationToSurface();

vtkNew<vtkRenderer> renderer;
renderer->AddActor(actor);

window->AddRenderer(renderer);

// setup initial status
std::mt19937 randEng(0);
::Randomize(sphere, mapper, window, randEng);

// connect the buttons
QObject::connect(&randomizeButton, &QPushButton::released,
[&]() { ::Randomize(sphere, mapper, window, randEng); });

mainWindow.show();

return app.exec();
}

namespace
{
void Randomize(vtkSphereSource* sphere, vtkMapper* mapper, vtkGenericOpenGLRenderWindow* window,
std::mt19937& randEng)
{
// generate randomness
double randAmp = 0.2 + ((randEng() % 1000) / 1000.0) * 0.2;
double randThetaFreq = 1.0 + (randEng() % 9);
double randPhiFreq = 1.0 + (randEng() % 9);

// extract and prepare data
sphere->Update();
vtkSmartPointer<vtkPolyData> newSphere;
newSphere.TakeReference(sphere->GetOutput()->NewInstance());
newSphere->DeepCopy(sphere->GetOutput());
vtkNew<vtkDoubleArray> height;
height->SetName("Height");
height->SetNumberOfComponents(1);
height->SetNumberOfTuples(newSphere->GetNumberOfPoints());
newSphere->GetPointData()->AddArray(height);

// deform the sphere
for (int iP = 0; iP < newSphere->GetNumberOfPoints(); iP++)
{
double pt[3] = { 0.0 };
newSphere->GetPoint(iP, pt);
double theta = std::atan2(pt[1], pt[0]);
double phi = std::atan2(pt[2], std::sqrt(std::pow(pt[0], 2) + std::pow(pt[1], 2)));
double thisAmp = randAmp * std::cos(randThetaFreq * theta) * std::sin(randPhiFreq * phi);
height->SetValue(iP, thisAmp);
pt[0] += thisAmp * std::cos(theta) * std::cos(phi);
pt[1] += thisAmp * std::sin(theta) * std::cos(phi);
pt[2] += thisAmp * std::sin(phi);
newSphere->GetPoints()->SetPoint(iP, pt);
}
newSphere->GetPointData()->SetScalars(height);

// reconfigure the pipeline to take the new deformed sphere
mapper->SetInputDataObject(newSphere);
mapper->SetScalarModeToUsePointData();
mapper->ColorByArrayComponent("Height", 0);
window->Render();
}
} // namespace

结果显示

赞(0)
未经允许不得转载:网硕互联帮助中心 » QT中使用QVTKOpenGLNativeWidget显示三维图形(VTK9.x以上版本)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!