VTK 仔细分析一个复杂程序

1.程序代码

 1 #include <vtkAutoInit.h>
 2 VTK_MODULE_INIT(vtkRenderingOpenGL);
 3 /
 4 #include <vtkSmartPointer.h>
 5 #include <vtkRenderWindow.h>
 6 #include <vtkRenderer.h>
 7 #include <vtkRenderWindowInteractor.h>
 8 #include <vtkInteractorStyleTrackballCamera.h>
 9 #include <vtkCylinderSource.h>
10 #include <vtkPolyDataMapper.h>
11 #include <vtkActor.h>
12  
13 int main()
14 {
15     //构造数据源
16     vtkSmartPointer<vtkCylinderSource> cylinder = 
17         vtkSmartPointer <vtkCylinderSource>::New();
18     cylinder->SetHeight(3.0);
19     cylinder->SetRadius(1.0);
20     cylinder->SetResolution(10);
21     //生成VTK数据结构
22     vtkSmartPointer<vtkPolyDataMapper> cylinderMapper=
23         vtkSmartPointer<vtkPolyDataMapper>::New();
24     cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
25     //给演员化妆
26     vtkSmartPointer<vtkActor> cylinderActor =
27         vtkSmartPointer<vtkActor>::New();
28     cylinderActor->SetMapper(cylinderMapper);
29     //布置舞台
30     vtkSmartPointer<vtkRenderer> cylinderRenderer =
31         vtkSmartPointer<vtkRenderer>::New();
32     cylinderRenderer->AddActor(cylinderActor);
33     cylinderRenderer->SetBackground(1,0,0);
34     //装饰剧院
35     vtkSmartPointer<vtkRenderWindow> renwin=
36         vtkSmartPointer<vtkRenderWindow>::New();
37     renwin->AddRenderer(cylinderRenderer); //搭建舞台
38     renwin->SetSize(400,400);
39     //观众席和舞台的互动
40     vtkSmartPointer<vtkRenderWindowInteractor> renwininter=
41         vtkSmartPointer<vtkRenderWindowInteractor>::New();
42     renwininter->SetRenderWindow(renwin);
43     //观众席的行为(单方面互动)
44     vtkSmartPointer<vtkInteractorStyleTrackballCamera> style=
45         vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
46     renwininter->SetInteractorStyle(style);
47  
48     renwininter->Initialize(); //初始化
49     renwininter->Start();      //等待交互手段(事件)
50     return 0;
51 }

2.代码分析及释义

上述程序可以完成鼠标与圆柱交互,比如放大、缩小,平移、旋转等。

2.1 vtkCylinderSource:

派生自vtkPolyDataAlgorithm。顾名思义,vtkCylinderSource生成的数据类型就是PolyData(vtkPolyData)的,它主要是生成一个中心在渲染场景原点的柱体,柱体的长轴沿着Y轴,柱体的高度、截面半径等都可以任意指定。
vtkCylinderSource::SetHeight() ——设置柱体的高。
vtkCylinderSource::SetRadius() ——设置柱体横截面的半径。
vtkCylinderSource::SetResolution() ——设置柱体横截面的等边多边形的边数。转动一下柱体,然后数数柱体横截面有多少条边,应该就能明白这个参数表示什么意思。

2.2  vtkPolyDataMapper:

渲染多边形几何数据(vtkPolyData),派生自类vtkMapper,将输入的数据转换为几何图元(点、线、多边形)进行渲染。vtkPolyDataMapper::SetInputConnection() —— VTK可视化管线的输入数据接口,对应的可视化管线输出数据的接口为GetOutputPort();VTK5.0之前的版本使用SetInput()和GetOutput()作为输入输出接口,VTK 5.0以后版本保留了对这两个接口的支持。

2.3 vtkActor:

派生自vtkProp类,渲染场景中数据的可视化表达是通过vtkProp的子类负责的。比如,本例要渲染一个柱体,柱体的数据类型是vtkPolyData,数据要在场景中渲染时,不是直接把数据加入渲染场景就可以,待渲染的数据是以vtkProp的形式存在于渲染场景中。三维空间中渲染对象最常用的vtkProp子类是vtkActor(表达场景中的几何数据)和vtkVolume(表达场景中的体数据);二维空间中的数据则是用vtkActor2D表达。vtkProp子类负责确定渲染场景中对象的位置、大小和方向信息。Prop依赖于两个对象,一个是Mapper(vtkMapper)对象,负责存放数据和渲染信息,另一个是属性(vtkProperty)对象,负责控制颜色、不透明度等参数。
VTK中定义了大量(超过50个)的Prop类,如vtkImageActor(负责图像显示)和vtkPieChartActor(用于创建数组数据的饼图可视化表达)。其中的一些Prop内部直接包括了控制显示的参数和待渲染数据的索引,因此并不需要额外的Property和Mapper对象。vtkActor的子类vtkFollower可以自动的更新方向信息以保持始终面向一个特定的相机。这样无论怎样旋转,三维场景中的广告板(Billboards)或者文本都是可见的。vtkActor的子类vtkLODActor可以自动改变自身的几何表达来实现需要达到的交互帧率。vtkProp3D的子类vtkLODProp3D则是通过从许多Mapper(可以是体数据的Mapper和几何数据的Mapper集合)中进行选择来实现交互。vtkAssembly建立Actor的等级结构以便在整个结构平移、旋转或者缩放时能够更合理的控制变换。
vtkActor::SetMapper()——设置生成几何图元的Mapper。即连接一个Actor到可视化管线的末端(可视化管线的末端就是Mapper)。

2.4  vtkRenderWindow:

将操作系统与VTK渲染引擎连接到一起。不同平台下的vtkRenderWindow子类负责本地计算机系统中窗口创建和渲染过程管理。当使用VTK开发应用程序时,你只需要使用平台无关的vtkRendererWindow类,运行时,系统会自动替换为平台相关的vtkRendererWindow子类。比如,Windows下运行上述的VTK程序,实际创建的是vtkWin32OpenGLRenderWindow(vtkRenderWindow的子类)对象。vtkRenderWindow中包含了vtkRenderer集合、渲染参数,如立体显示(Stereo),反走样,运动模糊(Motion Blur)和焦点深度(Focal Depth)等。
vtkRenderWindow::AddRenderer() ——加入vtkRenderer对象。
vtkRenderWindow::SetSize() ——该方法是从vtkRenderWindow的父类vtkWindow继承过来的,用于设置窗口的大小,以像素为单位。

2.5 vtkRenderer:

负责管理场景的渲染过程。组成场景的所有对象包括Prop,照相机(Camera)和光照(Light)都被集中在一个vtkRenderer对象中。一个vtkRenderWindow中可以有多个vtkRenderer对象,而这些vtkRenderer可以渲染在窗口中不同的矩形区域中(即视口),或者覆盖整个窗口区域。
vtkRenderer::AddActor() ——添加vtkProp类型的对象到渲染场景中。
vtkRenderer::SetBackground() ——该方法是从vtkRenderer的父类vtkViewport继承的,用于设置渲染场景的背景颜色,用R、G、B的格式设置,三个分量的取值为0.0~ 1.0。除了可以设置单一的背景颜色之外,还可以设置渐变的背景颜色,vtkViewport::SetBackground2()用于设置渐变的另外一种颜色,但是要使背景颜色渐变生效或者关闭,必须调用以下的方法:
vtkViewport::SetGradientBackground(bool) ——参数为0是关闭,反之,打开。
vtkViewport::GradientBackgroundOn()—— 打开背景颜色渐变效果,相当于调用方法SetGradientBackground(1)。
vtkViewport::GradientBackgroundOff() ——关闭背景颜色渐变效果。相当于调用方法SetGradientBackground(0)。

2.6 vtkRenderWindowInteractor:

提供平台独立的响应鼠标、键盘和时钟事件的交互机制,通过VTK的Command/Observer设计模式将监听到的特定平台的鼠标、键盘和时钟事件交由vtkInteractorObserver或其子类,如vtkInteractorStyle进行处理。vtkInteractorStyle等监听这些消息并进行处理以完成旋转、拉伸和放缩等运动控制。vtkRenderWindowInteractor自动建立一个默认的3D场景交互器样式(Interactor Style):vtkInteractorStyleSwitch,当然你也可以选择其他的交互器样式,或者是创建自己的交互器样式。在本例中,我们就是选择了其他的交互器样式来替代默认的:vtkInteractorStyleTrackballCamera。
vtkRenderWindowInteractor::SetRenderWindow()——设置渲染窗口,消息是通过渲染窗口捕获到的,所以必须要给交互器对象设置渲染窗口。
vtkRenderWindowInteractor::SetInteractorStyle()——定义交互器样式,默认的交互样式为vtkInteractorStyleSwitch。
vtkRenderWindowInteractor::Initialize() ——为处理窗口事件做准备,交互器工作之前必须先调用这个方法进行初始化。
vtkRenderWindowInteractor::Start() ——开始进入事件响应循环,交互器处于等待状态,等待用户交互事件的发生。进入事件响应循环之前必须先调用Initialize()方法。

2.7 vtkInteractorStyleTrackballCamera:

交互器样式的一种,该样式下,用户是通过控制相机对物体作旋转、放大、缩小等操作。做个类比:我们在照相的时候如果要想物体看起来显得大一些,我们可以采取两种做法,第一种做法是相机不动,让我们要拍的物体靠近我们;第二种做法是物体不要动,我们把相机靠近物体,这样物体看起来也是大一些。第二种做法就是vtkInteractorStyleTrackballCamera的风格。其父类为vtkInteractorStyle,除了vtkInteractorStyleTrackballCamera之外,VTK还定义了其他多种交互器样式,如vtkInteractorStyleImage,主要用于显示二维图像时的交互。

3.东灵的形象化讲解

当我们去看舞台剧的时候,我们坐在台下,展现在我们面前的是一个舞台,舞台上有各式的灯光,各样的演员。演员出场的时候肯定是会先化妆,有些演员可能会打扮成高富帅,有些演员可能会化妆成白富美。观众有时还会与台上的演员有一定的互动。
整个剧院就好比VTK程序的渲染窗口(vtkRenderWindow);舞台就相当于渲染场景(vtkRenderer);而那些高富帅、白富美就是我们程序中的Actor(有些文献翻译成“演员”,有些翻译成“角色”,这里我们不作翻译);台上的演员与台下观众的互动可以看成是程序的交互(vtkRenderWindowInteractor);演员与观众的互动方式有很多种,现场的观众可以直接上台跟演员们握手拥抱,电视机前的可以发短信,电脑、移动终端用户等可以微博关注、加粉等等,这就好比我们程序里的交互器样式(vtkInteractorStyle);舞台上的演员我们都能一一分辨出来,不会把高富帅弄混淆,是因为他们化的妆、穿的服饰都不一样,这就相当于我们程序里vtkActor的不同属性(vtkProperty);台下观众的眼睛可以看作是vtkCamera,前排的观众因为离得近,看台上演员会显得比较高大,而后排的观众看到的会显得小点,每个观众看到的东西在他的世界里都是唯一的,所以渲染场景Renderer里的vtkCamera对象也是只有一个;舞台上的灯光可以有多个,所以渲染场景里的vtkLight也存在多个。可以参考下图,加深理解:

4.本程序的运行结果

可以使用鼠标与柱体交互,比如用鼠标滚轮可以对柱体放大、缩小;按下鼠标左键不放,然后移动鼠标,可以转动柱体;按下鼠标左键,同时按下Shift键,移动鼠标,可以移动整个柱体,等等。
原文地址:https://www.cnblogs.com/ybqjymy/p/14240933.html