VTK②基础功能
基础功能里面有太多需要理解的东西了,从vtkRenderWindowInteractor, vtk Filter, vtkCamera, vtkLight开始吧
vtkRenderWindowInteractor
当对自己的数据做可视化的时候,显然咱得和可视化之后的数据有交互。所以尽管是非核心功能,也得有所了解。基本上,VTK提供了如下几种可选的方式:
- 使用内建的vtkRenderWindowInteractor
- 创建自己的交互器绑定相应的事件
- 如果使用解释型语言,可以在运行时输入命令
- 从屏幕上选取数据可以用“Picking”
最简单的方法当然就是用内建的vtkRenderWindowInteractor了,这个类已经为一系列预定义的事件和行为提供了响应,并且提供了override默认行为的方式。它允许咱们去控制Camera和Actor, 并且提供两种交互方式:①Position Sensitive,比如游戏操纵杆;②Motion Sensitive,比如轨迹球;下面就是已经定义好的事件响应(这里要特别指出的是,多个renderers可以渲染在同一个renderwindow,每个renderer有自己的viewport,而vtkRenderWindowInteractor支持和同一renderwindow中的多个render交互)
j键 和 t键: 在position sensitive(Joystick)和motion sensitive(Trackball)两种模式中切换。在J模式下,只要按鼠标键就可以持续运动;在T模式下,只有按着鼠标键拖动鼠标的时候,运动才会发生。
c键 和 a键: c代表Camera, a代表Actor。在C模式下,鼠标事件影响camera的位置和focalpoint;在A模式下,影响被鼠标指着的actor。
鼠标按键1, 2, 3
按键 模式 说明 Button 1 Camera 让Camera绕其FocalPoint旋转 Button 1 Actor 让Actor绕其原点旋转 Button 2 Camera 平移Camera Button 2 Actor 平移Actor Button 3 Camera 缩放Camera Button 3 Actor 缩放Actor 数字按键3: 切换render window的stereo mode
按键e 或者 q: 退出应用
按键f: 飞到鼠标点中的点,这事实上设置了focal point,然后允许围绕这个点旋转
按键p: 提供 Pick 操作
按键r: 重置camera
按键s: 让所有的actor都有表面
按键u: 进入用户定义的模式,也就是提供一个交互器,允许用户输入命令
按键w: 和s是反向的,显示actor的三维线框模型
默认的交互style是position sensitive也就是J模式。
vtkRenderWindowInteractor还提供了另外一些有用的特性。
- 比如默认的LightFollowCameraOn()会让light的位置和focal point和camera的位置和focal point保持同步。(当然,这个可以用LightFollowCameraOff()来关闭)
- 用来响应【按键U模式】的回调,可以AddObserver(UserEvent)
- 提供数种pick相关的方法,并AddObserver(StartPickEvent和EndPickEvent),还可以通过使用SetPicker()来继承vtkAbstractPicker,从而提供自定义的方法
另外,如果基于这些交互想调整渲染的质量的话,可以通过SetDesiredUpdateRate()来设置希望的帧率。通常情况下,这个是自动处理的(鼠标激活,帧率提升,鼠标释放,帧率恢复)
在VTK中,有两种不同的控制交互的方式:
- 子类化 vtkInteractorStyle
1
2my_style = vtkInteractorStyleFlight()
iren.SetInteractorStyle(my_style) # iren是一个vtkRenderWindowInteractor的实例 - 在vtkRenderWindowInteractor增加oberservers,然后自定义一系列回调(3D 组件比较复杂, 以后另有专题)
案例就参考 Examples/GUI/Python/CustomInteraction.py
Filter Data
这个容易理解多了,基本上可以看做Linux下面的管道的概念,继续拿CADPART来做说明:
1 | part = vtk.vtkSTLRead() |
示意如下,需要注意的就是需要确保管道前后的数据类型的兼容:
1 | graph LR |
vtkCamera
在3D图像处理中,Camera和Light对于渲染对象来说是非常重要的,所以如果程序没有显式声明的话,VTK会默认实例化camera和light。
实例化一个相机,并和渲染实例联系起来
1
2
3
4
5
6
7cam1 = vtk.vtkCamera() #实例化一个camera
cam1.SetClippingRange(0.0475572, 2.37786) #设定Clipping的范围,最近和最远,不在这个范围内的物体都自动被清除
cam1.SetFocalPoint(0052665, -0.129454, -0.0573973) #方向
cam1.SetPosition(0.327637, -0.116299, -0.256418) #位置
cam1.ComputeViewPlaneNormal() # 默认的方式-这个需要具体学习一下
cam1.SetViewUp(-0.0225386, 0.999137, 0.034901) # 相机向上的方向
ren1.SetActiveCamera(cam1)获得当前已经存在的相机实例
1
2cam1 = ren1.GetActiveCamera()
cam1.Zoom(1.4) # 通过改变视角来了缩放(也可参考SetViewAngle()),另外还有Dolly()通过移动相机来缩放其他简单的操纵相机的方法【需要进一步理解】
1
2
3
4cam1.Azimuth(150) # 相机以Focal Point为中心的球型轨迹移动的经度
cam1.Elevation(160) # 相机以Focal Point为中心的球型轨迹移动的维度
""" 要注意的就是一般情况下不会改变view-up vector,但是在南北极点会和view plane平行 """
""" 为了避免这种情况,需要强制使用OrthogonalizeViewUp()方法(正交),这种情况会改变相机协同轨迹 """控制View的方向
相机最基础的功能是产生一个特定方向的视图,在程序上是通过这样的步骤来实现的:
- 设置相机的Focal Point
cam1.SetFocalPoint(0, 0, 0) #x, y, z - 设置相机的Position
cam1.SetPosition(1, 1, 1) #x,y, z - 设置相机的ViewPanel
cam1.ComputeViewPlaneNormal() - 设置相机的ViewUp
cam1.SetViewUp(1, 0, 0) - 设置相机是否正交
cam1.OrthogonalizeViewUp() - 设置相机为当前相机
ren1.SetActiveCamera(cam1) - 重置相机
ren1.ResetCamera()
也就是说:1
2
3graph LR
A[设置相机基本属性] --> B[激活相机为当前相机]
B --> C[重置舞台渲染的相机]
- 透视(Perspective)和正交(Orghogonal)
- 透视视图是通过视角(view angle)来调节角色(Actor)在View Plane上的成像的【点光源】
- 正交或者平行视图可以想象成【平行光】,物体的成像是不受距离影响的
要开启正交视图,首先用cam1.ParallelProjectionOn()
在正交视图中,视角不在用来控制缩放,而必须使用cam1.SetParallelScale() - 保存和恢复相机状态
这其实不用多做介绍,保存相机状态,至少需要保存Position、Focal Point、Clipping Range和View Up;恢复的话首先用保存的参数实例化一个相机,然后多一个步骤就是要ren1.SetActiveCamera()
DNvtkLight
灯光比相机容易控制,最常用的方法就是SetPosition(),SetFocalPoint()和SetColor();另外,相机的灯光可以用SwitchOn()和SitchOff()开关;用SetIntensity()来控制强度 - 默认的vtkLight实例是定向灯光,也就是说其位置(position)和焦点(focal point)定义了一个平行于光线行进方向的矢量,并且光源假定在无穷远处。这意味着如果位置和焦点被同样地改变的话,物体上的光照不变。
通常,我们用如下的定义灯光,比如红色的头灯,位于相机的位置,指向相机的焦点。1
2
3
4
5light = vtk.vtkLight()
light.SetColor(1, 0, 0)
light.SetFocalPoint(cam1.GetFocalPoint())
light.SetPosition(cam1.GetPosition())
ren1.AddLight(light) - 定点光源Positional Lights【需要进一步理解】
使用PositionalOn()可以创建一个定点光源,可以和SetConeAngle()一起使用来控制聚光的面积,如果是180度的锥角的话,表明没有聚光效果而只有位置效果。