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键,移动鼠标,可以移动整个柱体,等等。