一、程序
#include <QtCore/QCoreApplication>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
vtkSmartPointer<vtkCylinderSource> cylinder = vtkSmartPointer<vtkCylinderSource>::New();
cylinder->SetHeight(3.0); //圆柱体高
cylinder->SetRadius(1.0); //圆柱体横截面的半径
cylinder->SetResolution(10); //分辨率(圆柱体边数)
vtkSmartPointer<vtkPolyDataMapper> cylinderMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
cylinderMapper->SetInputConnection(cylinder->GetOutputPort());
vtkSmartPointer<vtkActor> cylinderActor = vtkSmartPointer<vtkActor>::New();
cylinderActor->SetMapper(cylinderMapper);
cylinderActor->GetProperty()->SetColor(1.0, 0.0, 0.0); //red
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(cylinderActor);
renderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(renderer);
renWin->SetSize(640, 480);
renWin->Render();
renWin->SetWindowName("RenderCylinder");
vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow(renWin);
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
iren->SetInteractorStyle(style);
iren->Initialize();
iren->Start();
return a.exec();
}
二、分析
(1) vtkCylinderSource
该类派生自vtkPolyDataAlgorithm。顾名思义,vtkCylinderSource生成的数据类型就是vtkPolyData,它主要是生成一个中心在渲染场景原点的柱体,柱体的长轴沿着Y轴,柱体的高度、界面半径等都可以任意指定。
vtkCylinderSource::SetHight():设置柱体的高。
vtkCylinderSource::SetRadius():设置柱体横截面的半径。
vtkCylinderSource::SetResolution():设置柱体横截面的等边多边形的边数。Resolution本意为分辨率,这里表示边数。
(2)vtkPolyDataMapper
该类用于渲染多边形几何数据(vtkPolyData),派生自类vtkMapper,将输入的数据转换为几何图元(点、线、多边形)进行渲染。
vtkPloyDataMapper::SetInputConnection():VTK可视化管线的输入数据接口,对应的可视化管线的输出数据接口为GetOutputPort();VTK5.0之前的版本使用SetInput()和GetOutput()作为输入输出接口,VTK5.X版本保留了对这两个接口的支持。
(3)vtkActor
该类派生自vtkProp类,渲染场景中数据的可视化表达通过vtkProp的子类负责。比如该示例要渲染一个柱体,柱体的数据类型是vtkPolyData,数据在场景中渲染时,不是直接把数据加入渲染场景,而是以vtkProp的形式存在于渲染场景中。三维空间中渲染对象最常用的vtkProp子类有vtkActor(表达场景中的几何数据)和vtkVolume(表达场景中的体数据);二维空间中的数据则是vtkActor2D表达:vtkProp子类负责确定渲染场景中对象的位置、大小和方向等信息;另一个熟悉(vtkProperty)对象,负责控制颜色、不透明度等参数。另外,vtkActor中还可以设置纹理(vtkTexture)对象,用于纹理贴图。
VTK定义了大量的Prop类,如vtkImageActor(负责图像显示)和vtkPieChartActor(用于创建数组数据的饼图可视化表达形式)。其中有些Prop内部直接包括了控制显示的参数和待渲染数据的索引,因此并不需要额外的Property和Mapper对象,例如vtkAxisActor。vtkActor的子类vtkFollower可以自动更新方向信息使其始终面向一个特点的相机,这样无论怎样选择该对象都是可见的,例如三维场景中的广告板或者文本。vtkActor的子类vtkLODActor可以自动改变自身的几何表达形式来实现所需的交互帧率。vtkAssembly建立了各个Actor的层次结构以便在整个结构平移、旋转或缩放等变换是能够更合理地进行控制。
vtkActor::SetMapper():该方法用于设置生成几何图元的Mapper,即连接一个Actor到可视化管线的末端(Mapper是可视化管线的末端)。
(4)vtkRenderWindow
将操作系统与VTK渲染引擎连接到一起。不同平台下的vtkRenderWindow子类负责管理本地计算机系统中窗口创建和渲染过程。当时用VTK开发应用程序时,只需要使用平台无关的vtkRenderWindow类,运行时,系统会自动替换为平台相关的vtkRendererWindow子类。比如,Windows下运行上述的VTK程序,实际创建的是vtkWin32OpenGLRenderWindow(vtkRenderWindow的子类)对象。vtkRenderWindow中包含了vtkRenderer集合、渲染参数,如立体显示(Stereo)、反走样、运动模糊(Motion Blur)和焦点深度(Focal Depth)等。
vtkRenderWindow::AddRenderer():该方法用于加入vtkRenderer对象。
vtkRenderWindow::SetSize():该方法是从vtkRenderWindow的父类vtkWindow继承过来的,用于设置窗口的大小,以像素为单位。
(5)vtkRenderer
负责管理场景的渲染过程。组成场景的对象包括Prop,照相机(vtkCamera)和光照(vtkLight)都被整合到一个vtkRenderer对象中。一个vtkRenderWindow中可以有多个vtkRenderer对象,而这些vtkRenderer可以渲染在窗口不同的巨型区域中(即视口)或者覆盖整个窗口区域。
vtkRenderer::AddActor():该方法用于将vtkProp类型的对象添加到渲染场景中。
vtkRenderer::SetBackground():该方法是从vtkRenderer的父类vtkViewport继承的,用于设置渲染场景的背景颜色,用RGB的格式设置,三个分量的取值为0.0~1.0。(0.0,0.0,0.0)为黑色,vtkViewport::SetBackground2()用于设置渐变的另外一种颜色,但是要使背景颜色渐变生效或者关闭,必须调用以下的方法。
vtkViewport::SetGradientBackground(bool):参数为0时,关闭,反之,打开。
vtkViewport::GradientBackgroundOn():该方法用于打开背景颜色渐变效果,相当于调用SetGradientBackground(1)。
vtkViewport::GradientBackgroundOff():该方法用于打开背景颜色渐变效果,相当于调用SetGradientBackground(0)。
(6)vtkRenderWindowInteractor
提供平台独立的响应鼠标、键盘和时钟事件的交互机制,通过VTK的观察者/命令模式将监听的特定平台的鼠标、键盘和时钟事件交由vtkInteractorObserver或其子类,如vtkInteractorStyle进行处理。vtkInteractorStyle等监听这些消息并进行处理以完成旋转、拉伸和缩放等运动控制。
vtkRenderWindowInteractor会自动建立一个默认的3D场景交互器样式(Interactor Style):vtkInteractorStyleSwitch,当然也可以选择其他交互器样式或者创建自己的交互器样式,如本例中使用的vtkInteractorStyleTrackballCamera。
vtkRenderWindowInteractor::SetRenderWindow():该方法用于设置渲染窗口,消息是通过渲染窗口捕获到的,所以必须给交互对象设置渲染窗口。
vtkRenderWindowInteractor::SetInteractorStyle():该方法用于定义交互器样式,默认的交互器样式为vtkInteractorStyleSwitch。
vtkRenderWindowInteractor::Initialize():该方法表示为处理窗口事件做准备,交互器工作之前必须先调用这个方法进行初始化。
vtkRenderWindowInteractor::Start():该方法表示开始进入事件响应循环,交互器处于等待状态,等待用户交互事件的发生。进入事件响应循环之前必须调用Initialize()方法。
(7)vtkInteractorStyleTrackballCamera
交互器样式的一种。该样式下,用户通过控制相机对物体作旋转、放大、缩小等操作。打个比方,在照相时如果想要物体拍起来显得大一些,可以采取两种做法:第一种做法是相机不定,让要拍的物体靠近相机;第二种做法是物体不动,让相机靠近物体。第二种做法就是vtkInteractorStyleTrackballCamera的风格。其父类为vtkInteractorStyle,除了vtkIntearctorStyleTrackballCamera之外,VTK还定义了其它多种交互器样式,如vtkInteractorStyleImage,主要用于显示二维图像时的交互。
三、东灵的讲解
整个剧院就好比VTK程序的渲染窗口(vtkRenderWindow);舞台就相当于渲染场景(vtkRenderer);而那些演员就是程序中的Actor,台上演员与台下观众的互动就可以看作与应用程序的交互(vtkRenderWindowInteractor);演员与观众的互动方式有很多种,现场的观众可以直接上台跟演员们握手拥抱,电视机前的可以发短信,计算机前的可以微博关注等,这就好比程序中的交互器样式(vtkInteractorStyle);对于舞台上的演员,观众都可以一一分辨出来,不会弄混,是因为他们穿着打扮、容貌都不一样,这就相当于程序中vtkActor的不同属性(vtkProperty);台下观众的眼睛就可以看作vtkCamera,前排的观众离得近,看演员觉得高大,而后排的观众离得远,觉得演员小些,每位观众看到的东西在他的世界里都是唯一的,所以渲染场景Renderer里的vtkCamera对象只有一个;舞台上的灯光可以有多个,所以渲染场景里的vtkLight也存在多个。
参考资料:
《VTK图形图像开发进阶》-东灵。