4.2 Using VTK Interactors
- VTK提供了两种和可视化结果互动的方法:
- 用系统自带的
vtkRenderWindowInteractor
- 创建自己的Interactor,绑定一些事件在上面
- 用系统自带的
- 如果是用解释性语言(python, tcl)编写的程序,还可以在运行时敲入命令来交互。
vtkRenderWindowInteractor
- 最简单的和可视化数据交互的方式就是例化一个
vtkRenderWindowInteractor
,这个类有一些事先设定好的事件(event)和动作(action),并且可以被override。它可以控制camera和actor,由两种交互风格(interaction style):- position sensitive (joystick mode) 操纵杆模式
- motion sensitive (trackball mode) 轨迹球模式
-
vtkRenderWindowInteractor
支持以下事件:- j / t : j是切换到joystick mode, t是切换到trackball mode。joystick模式下,鼠标在显示窗口中按住,动作就会持续发生;trackball模式下,鼠标按下并且拖动鼠标,动作才会发生。
- c / a : c是切换到camera控制,a是切换到actor控制。
- 鼠标左键:旋转
- 鼠标中键:拖动
- 鼠标右键:缩放
- 3:切换到红蓝3D显示,戴上红蓝眼镜能看到3D效果
- e:退出程序
- f:fly-to the point under the cursor,个人测试下来觉得是将物体以鼠标当前位置为中心显示出来。
-
p:进行pick操作,
vtkRenderWindowInteractor
有一个内置的vtkPropPicker
成员用来执行pick操作。(pick的含义在后文会解释) - r:reset,沿着当前的视角方向重置camera视角,将actor放置在中心,重置camera使得所有的actor都能显示出来。
- s:使所有的actors都以surface的形式显示
- u:在解释型语言中,按u来输入用户指令。
- w:使所有的actors都以wireframe的形式显示
4.3 Filtering Data
之前的例子都是source object直接连入mapper object,中间没有filters。filters的连接是通过SetInput()
和GetOutput()
方法。
这里举的一个例子就是在之前的例子中加入了一个filter。核心的代码如下:
// set filter
vtkShrinkPolyData shrink = vtkShrinkPolyData::New();
shrink->SetInput(part->GetOutput());
shrink->SetShrinkFactor(0.85);
// set Mapper
vtkPolyDataMapper partMapper = vtkPolyDataMapper::New();
partMapper->SetInput(shrink->GetOutput());
由于vtk这个例子只有python和tcl的版本,这里我就偷懒直接用python脚本运行了,要用vtk的python wrapper,可以用$VTK_BUILD/bin/vtkpython,在/usr/local/bin中也有vtkpython,但不知道为何显示import vtk
失败,可能是环境变量没有配置好,不过在vtk安装目录下的那个是可以用的,运行结果如下:
这个shrink filter的含义从字面上没法理解,有待进一步研究……
4.4 Controlling The Camera
- 有两种方式来操控camera:
- 先例化camrea,再设置给renderer
vtkCamera cam1 = vtkCamera::New();
cam1->... // 设置cam1的属性
vtkRenderer ren1 = vtkRenderer::New();
ren1->SetActiveCamera(cam1);
- 从renderer中得到默认的camera,对其进行属性设置
cam1 = ren1->GetActiveCamera();
cam1->... // 设置cam1属性
- camera的属性设置在使用时才有体会,这个在日后的使用中可以逐渐学习。
4.5 Controlling Lights
- Light比camera更容易控制,常见的几个方法是
SetPosition()
,SetFocalPoint()
,SetColor()
。默认情况下,vtkLight
是一个平行光源,即光源在无限远的位置,投射在物体上的光线是平行的。 - 常用的Light设置为headlight,即light和camera的位置、焦点都一致。
4.6 Controlling 3D Props
- Prop这个词本意是舞台上的道具,在VTK里面引申为显示在窗口中的物体。
vtkActor
是vtkProp3D
的一个子类,它的几何构成由多边形和连线确定。
vtkProp3D的位置
- 我们已经看过如何控制camera来改变物体的显示。同样的,我们可以保持camera不变,直接控制Prop:
-
SetPosition(x, y, z)
:在世界坐标系(world coordinate)中指定vtkProp3D
的位置。 -
AddPosition(x, y, z)
:Translate the Prop. -
RotateX(theta)
,RotateY(theta)
,RotateZ(theta)
,绕坐标轴旋转theta角度。 -
SetOrientation(x, y, z)
:指定Prop的朝向,先调整Z轴,其次X,最后Y轴。 -
AddOrientation(x, y, z)
:在现有的朝向上增加角度。 -
RotateWXYZ(theta, x, y, z)
:以指定的xyz向量旋转Prop theta角度。 -
Scale(sx, sy, sz)
:在xyz轴上调整Prop的大小。 -
SetOrigin(x, y, z)
:设置Prop的原点,Prop的旋转和放大都是围绕着Origin操作的。
-
- 最重要的一点:上述这些操作在VTK中是以一个固定的顺序执行的:
Shift to Origin -> Scale -> Rotate Y -> Rotate X -> Rotate X -> Shift from Origin -> Translate
- 不同的操作顺序导致的结果会大相径庭。
Actors
- Actors是最常用的
vtkProp3D
子类,它把一系列的渲染属性例如表面属性(e.g. 反射光照),表现方式(e.g. surface模式/wireframe模式),材质贴图等集合在一起。(class的作用) - 定义Geometry数据来源用
SetMapper()
方法,之前已经见过多次。Mapper是连接Visualization pipeline和Graphics pipeline的桥梁。 -
vtkProperty
的class控制着Actor的属性,和camera一样,可以先例化再赋值(actor->SetProperty(property)
),或者先得到再写属性(actor->GetProperty()
)。 - 颜色可能是actor最重要的属性。
SetColor(doule r, double g, double b)
,rgb的值都在[0, 1]的范围内。也可以分别设置Ambient/Diffuse/Specular的颜色。 - Actor的透明度可以设置,尤其在需要看到内部结构的时候有用。
actor->GetProperty()->SetOpacity(double opacity);
。透明度的渲染是用了α-blending的方法,所以当有多个透明actor时,渲染的顺序尤为重要,最好是把透明的actor放在渲染列表的最后(这一段现在还不是很理解 TODO)
Level-Of-Detail Actors
- 加入了interactor之后,它会自动控制显示的帧率,在运动时以高帧率/低分辨率显示,在静止时以低帧率/高分辨率显示
Assemblies
- Actors可以被组合成有层次的集合,当assembly中一个actor运动的时候,其他actor也会随之而动。例如机器人的手臂可能由上臂、小臂、手腕、手构成,他们之间通过joint连接,而上臂绕着肩膀旋转时,下面的部分也应该跟着旋转。这时就可以用到Assembly,它也是
vtkActor
的一个子类。
-
vtkAssembly
尽管是vtkActor
的子类,但它并没有自身的Property和Mapper,只能设置它的Position信息。因此Assembly内部的元素必须自身包含了各自的属性和连接的Mapper。 - Assembly可以层级包含,在最后renderer中
AddActor()
时只需要添加最外围的Assembly,里面的各个元素包括内部的小Assembly会递归渲染。一个actor可以被包含在多个Assembly中,只要不出现自身包含自身的情况即可。
Volumes
- 回忆上一章中,
vtkProp3D
主要有两个子类:vtkActor
和vtkVolume
,vtkVolume
也从vtkProp3D
中继承了一系列操作position和orientation的方法,此外,它也有自身的属性设置vtkVolumeProperty
。(Volume这个词的含义还需要探究,有些资料里说是“体渲染” TODO) 下面是一个Volume的例子: