文章目录
如何通过VTK渲染一个圆柱体
1.创建圆柱体数据源
auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
cylinder->SetHeight(3.0);
cylinder->SetRadius(1.0);
cylinder->SetResolution(15);
vtkCylinderSource是VTK中的一个源对象(source),专门用来生成几何形状为圆柱体的数据,它可以根据设置的参数(如高度,半径和分辨率)生成圆柱体的顶点、边和多边形面等几何数据。vtkCylinderSource派生自vtkPolyDataAlgorithm。
vtkCylinderSource::SetHeight:设置圆柱体的高度。
vtkCylinderSource::SetRadius:设置圆柱体的横截面半径。
vtkCylinderSource::SetResolution:设置柱体横截面的等边多边形的边数,上述代码的圆周上生成的多边形片段数量为15。较高的分辨率意味着圆柱体的圆形部分看起来会更平滑。
vtkCylinderSource生成的数据类型是vtkPolyData,它主要是生成一个中心在渲染场景原点的柱体,柱体的长轴沿着Y轴。换句话说vtkPolyData是VTK中用于存储和表示几何数据的一个常见数据结构。它主要包括以下信息:
顶点(points):3D控件中的坐标。
边(lines):链接顶点的线段。
多边形面(polygons):由顶点和边围成的多边形(如三角形、四边形)。
属性(attributes):可以包括法向量、纹理坐标、标量值等,用户控制渲染时的视觉效果。
vtkPolyData可以存储非常复杂的几何对象,包括点、线、多边形、网格等。它是VTK中最常用的数据结构之一,适用于表示3D模型的几何信息。
vtkCylinderSource 和 vtkPolyData 的关系?
当我们使用vtkCylinderSource生成圆柱体时,它输出的数据格式是 vtkPolyData。也就是说圆柱体的几何信息(顶点、边、多边形)都被存储在一个vtkPolyData对象中。我们可以通过GetOutput()或GetOutputPort()获取vtkCylinderSourced的输出数据,这个输出对象就是一个vtkPolyData对象。
auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
cylinder->SetHeight(3.0);
cylinder->SetRadius(1.0);
cylinder->SetResolution(15);
// 获取 vtkCylinderSource 的输出端口,它是 vtkAlgorithmOutput 类型,实际指向的是 vtkPolyData
vtkAlgorithmOutput* outputPort = cylinder->GetOutputPort();
// 将 vtkAlgorithmOutput 连接到映射器,映射器最终会处理 vtkPolyData 数据
auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cylinderMapper->SetInputConnection(outputPort);
// cylinder->GetOutputPort() 直接返回了一个 vtkPolyData 对象,这个对象包含了圆柱体的几何数据。
vtkSmartPointer<vtkPolyData> polyData = cylinder->GetOutput();
从上述的代码可以看出,在VTK中,GetOutput()和GetOutputPort()是两种不同的方法,它们的作用并不相同。
GetOutput()
作用:GetOutput()方法用于直接获取算法的输出数据对象。
返回类型:它返回的是具体的数据对象。
使用场景:当我们想直接操作和访问某个算法生成的具体数据时(如几何体、图像、体数据),就可以使用GetOutput()。
GetOutputPort()
作用:GetOutputPort()方法用于获取算法的输出端口(即vtkAlgorithmOutput),这个端口可以用于连接其他VTK管线组件(如映射器、过滤器)。
返回类型:它返回的是一个vtkAlgorithmOutput对象,代表算法的输出端口,而不是具体的数据对象。
使用场景:当我们想将当前算法的输出连接到另一个VTK管线组件时(如 vtkPolyDataMapper、vtkActor 等),这个时候就需要使用GetOutputPort()来连接两个组件。
总的来说就是,通常在构建 VTK 渲染管线时,我们更多使用 GetOutputPort(),因为它可以轻松连接到其他处理模块。而 GetOutput() 更适合当你需要直接访问和操作数据的时候,比如调试或做一些特定的数据处理。
2.将圆柱体数据映射为可渲染的多边形数据
auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
该类用于渲染多边形几何数据(vtkPolyData),派生自类vtkMapper,将输入的数据转换为几何图元(点、线、多边形)进行渲染。
vtkPolyDataMapper:将几何数据(如从vtkCylinderSource生成的圆柱体数据)转换为渲染器,即可视化数据。
GetOutputPort:圆柱体数据的输出端口。
SetInputConnection:VTK可视化管线的输入数据接口,可以将圆柱体数据的输出端口连接到映射器的输入端口,这样cylinderMapper就能获取到几何数据用于渲染。
3.创建一个 Actor 用于管理几何数据和属性
auto cylinderActor = vtkSmartPointer<vtkActor>::New();
// 设置颜色为红色 (R, G, B),设置颜色为白色
cylinderActor->GetProperty()->SetColor(1.0, 1.0, 1.0);
// 设置透明度为 0.5(半透明)
cylinderActor->GetProperty()->SetOpacity(0.5);
cylinderActor->SetMapper(cylinderMapper);
该类派生自vtkProp类,渲染场景在数据的可视化表达通过vtkProp的子类负责。就像我们现在要渲染一个圆柱体,圆柱体的数据类型是vtkPolyData,数据要在场景中渲染时,不是直接将数据加入到渲染场景中,而是以vtkProp的形式存在于渲染场景中的。三维空间中渲染对象最常用的vtkProp子类有vtkActor(表达场景中的几何数据)和vtkVolume(表达场景中的体数据);二维空间中的数据则是用vtkActor2D表达;vtkProp子类负责确定渲染场景中对象的位置、大小和方向等信息;Prop依赖两个对象;一个是Mapper(vtkMapper)对象,负责存放数据和渲染信息;另一个是属性(vtkProperty)对象,负责控制颜色、不透明度等参数。另外vtkActor中还可以设置纹理(vtkTexture)对象,主要用于纹理贴图。
vtkActor:代表3D场景中的一个实体,它持有几何数据的映射器(mapper),用于负责在场景显示该几何数据。
GetProperty:它的作用是用来获取该vtkActor对象的属性对象vtkProperty,vtkProperty用来控制和设置与渲染相关的各种视觉属性,如颜色、头透明度、光泽、线条宽度、表面光反射等。
SetMapper:为该vtkActor对象设置几何数据的映射器,这样该vtkActor对象就可以知道如何绘制圆柱体的几何形状。
vtkProperty是VTK中的一个类,它控制一个3D对象的外观,通过GetProperty()方法可以访问与vtkActor相关联的vtkProperty对象,从而修改该对象的外观设置。使用 GetProperty() 方法,可以非常灵活地调整和控制 3D 对象的外观效果。
常用的vtkProperty设置:
SetColor(double r, double g, double b):设置对象的RGB颜色,如SetColor(1.0, 0, 0)设置颜色为红色,参数是RGB的值,1.0表示红色通道的最大值,0.0表示绿色通道和蓝色通道为0,所以结果为纯红色。
SetOpacity(double opacity):设置对象的透明度,范围是[0.0, 1.0]。
光泽度(SetSpecular(double specular)):设置对象的光泽度。
环境光反射(SetAmbient(double ambient)):控制环境光的反射。
漫反射(SetDiffuse(double diffuse)):控制漫反射光的强度。
边框线宽(setLineWidth(double width)):设置线宽(对应线或边框)。
点大小(SetPointSize):设置点的大小(对于点类型的数据)。
4. 创建一个渲染器并添加 Actor
auto renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(cylinderActor);
renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色作为起始颜色
renderer->SetBackground2(0.5, 0.5, 0.8); // 浅蓝色作为结束颜色
renderer->GradientBackgroundOn(); // 启用渐变背景
vtkRenderer负责管理场景的渲染过程,组成场景的对象包括Prop,照相机(vtkCamera)和光照(vtkLight)都被整合到了一个vtkRender对象中。它决定场景中物体如何被渲染。
vtkRenderer::AddActor():该方法用于将vtkProp类型的对象添加到渲染场景中。
vtkRenderer::SetBackground():该方法是从vtkRenderer的父类vtkViewport继承的,用于设置渲染场景的背景颜色;用R、G、B的格式设置,三个分量的取值为0.0~1.0。(0.0, 0.0,0.0)为黑色,(1.0, 1.0, 1.0)为白色。除了可以设置单一的背景颜色之外,还可以设置渐变的背景颜色。换句话说使SetBackground用设置背景颜色的起始颜色,使用SetBackground2设置背景颜色的终止颜色。
但是如果要使背景颜色渐变生效或者关闭,必须调用以下的方法:
vtkViewport::SetGradientBackground(bool):参数为0时,关闭,反之,打开。
vtkViewport::GradientBackgroundOn():该方法用于打开背景颜色渐变效果,相当于调用方法SetGradientBackground(1)。
vtkViewport::GradientBackgroundOff():该方法用于关闭背景颜色渐变效果,相当于调用方法SetGradientBackground(0)
5. 创建一个渲染窗口并添加渲染器
auto renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkGenericOpenGLRenderWindow:代表实际显示图像的窗口,负责将渲染器的输出显示在屏幕上,在Qt中,它与QOpenGLWidget结合使用。vtkGenericOpenGLRenderWindow是vtkRenderWindow的一个子类,它专门用于OpenGL渲染。
AddRenderer:将创建的渲染器添加到渲染窗口中,这样渲染器生成的3D场景就可以在窗口中显示。
上面提到了vtkRenderWindow类,那么就简单的介绍一下它的应用场景,它和vtkGenericOpenGLRenderWindow的区别在哪?
vtkRenderWindow类和vtkGenericOpenGLRenderWindow类都是VTK中用于管理渲染窗口的类。
vtkRenderWindow是VTK中最基础的渲染窗口类,它用于创建和管理渲染窗口,并与操作系统的窗口系统进行交互。vtkRenderWindow会根据我们使用的操作系统自动选择合适的渲染后端,打个比方说,在Windows上会使用OpenGL或者DirectX,在macOS上使用OpenGL,Linux上也可以使用X11等。vtkRenderWindows适用于那些依赖于VTK内部管理窗口系统的应用程序,通常由VTK完全控制渲染上下文和事件循环。
vtkGenericOpenGLRenderWindow是vtkRenderWindow的一个子类,它专门用于OpenGL渲染,提供了与第三方库或框架(如Qt,SDL等)更灵活的集成方式。并剥离了对平台窗口系统的依赖,提供了更通用的OepnGL渲染接口。vtkGenericOpenGLRenderWindow设计用于与外部GUI框架(如Qt)无缝集成,这允许我们将VTK的渲染窗口嵌入到这些框架的窗口中。比如说,在使用Qt时,通常会将vtkGenericOpenGLRenderWindow与QVTKOpenGLNativeWidget一起使用,将VTK的渲染窗口嵌入到Qt的控件中。它允许我们自己创建和管理OpenGL渲染上下文。而不是依赖VTK自动创建。
6. 在 Qt 界面中显示渲染窗口
ui.openGLWidget->setRenderWindow(renderWindow);
openGLWidget:这是 Qt 界面中的一个 QOpenGLWidget,它用于在 Qt 应用中显示 OpenGL 渲染的内容。
setRenderWindow(renderWindow):将 VTK 的渲染窗口 renderWindow 与 QOpenGLWidget 关联起来,这样 QOpenGLWidget 就会显示渲染窗口的内容。
渲染圆柱体的示例
VTK的渲染窗口嵌入到Qt的控件中
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
QtVTKDemo::QtVTKDemo(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
this->setFixedSize(800, 600);
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
cylinder->SetHeight(3.0);
cylinder->SetRadius(1.0);
cylinder->SetResolution(15);
vtkSmartPointer<vtkPolyData> cylinderData = cylinder->GetOutput();
auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
auto cylinderActor = vtkSmartPointer<vtkActor>::New();
// 设置颜色为红色 (R, G, B),设置颜色为白色
cylinderActor->GetProperty()->SetColor(1.0, 1.0, 1.0);
// 设置透明度为 0.5(半透明)
cylinderActor->GetProperty()->SetOpacity(0.5);
cylinderActor->SetMapper(cylinderMapper);
auto renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(cylinderActor);
renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色作为起始颜色
renderer->SetBackground2(0.5, 0.5, 0.8); // 浅蓝色作为结束颜色
renderer->GradientBackgroundOn(); // 启用渐变背景
auto renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(100, 100);
ui.openGLWidget->setRenderWindow(renderWindow);
}
VTK内部管理窗口系统的应用程序
auto cylinder = vtkSmartPointer<vtkCylinderSource>::New();
cylinder->SetHeight(3.0);
cylinder->SetRadius(1.0);
cylinder->SetResolution(15);
vtkSmartPointer<vtkPolyData> cylinderData = cylinder->GetOutput();
auto cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
auto cylinderActor = vtkSmartPointer<vtkActor>::New();
// 设置颜色为红色 (R, G, B),设置颜色为白色
cylinderActor->GetProperty()->SetColor(1.0, 1.0, 1.0);
// 设置透明度为 0.5(半透明)
cylinderActor->GetProperty()->SetOpacity(0.5);
cylinderActor->SetMapper(cylinderMapper);
auto renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(cylinderActor);
renderer->SetBackground(0.1, 0.1, 0.1); // 深灰色作为起始颜色
renderer->SetBackground2(0.5, 0.5, 0.8); // 浅蓝色作为结束颜色
renderer->GradientBackgroundOn(); // 启用渐变背景
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->SetSize(300, 300);
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("Cylinder");
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindow->Render();
renderWindowInteractor->Start();