VTK Tutorial
VTK Tutorial
官方教程:https://examples.vtk.org/site/Cxx/#tutorial
关于如何编译运行,我使用官方的方法无法运行,下面介绍我使用的方法。我的配置是windows10 + vs2017 + vtk9.1 + cmake3.30。
第一步:使用cmake gui编译

第二步:
点击一次configure,会弹出一个对话框,选择你的vs版本,以及x64.

第三步:
点击一次后,gui中间可能是红的,不必管他,保证gui最下面出现Configuring done 即可。此时再点击一次Configure,应该就不报红了,然后点击generate。
第四步:
去build文件夹下,用vs打开.sln

改成release,再右键all_build,点击生成。

生成成功。

第五步:
去release文件夹下,执行exe

Step1
  此示例创建了一个圆锥体的多边形模型,然后将其渲染到屏幕上。它将圆锥体旋转 360 度,然后退出。大多数VTK程序的基本流程都是source -> mapper -> actor -> renderer -> renderwindow
代码流程
- 创建并设置圆锥源(source): 生成几何数据(例如,圆锥体的几何形状)。创建了一个 
vtkConeSource对象,设置了圆锥的高度、半径和分辨率。这个源对象负责生成圆锥体的几何数据。 - 创建 
vtkPolyDataMapper映射器(mapper):将几何数据映射到图形原语(如三角形)。vtkPolyDataMapper用于将几何数据(在本例中是圆锥的多边形数据)映射到图形原语(例如三角形)上,使得数据可以被渲染。通过SetInputConnection方法将圆锥的数据连接到映射器。 - 创建并设置演员 (
vtkActor)(actor):负责在场景中呈现物体(管理位置、颜色等属性)。vtkActor代表一个可渲染的对象。它是实际显示在场景中的对象,包含了映射器、颜色等信息。将圆锥的映射器设置到演员中,并且通过GetProperty()->SetColor设置了演员的颜色为 “Tomato”(番茄红)。 - 创建渲染器和渲染窗口(renderer):负责管理场景中的所有演员,执行渲染操作。 
vtkRenderer是负责渲染场景的对象,我们将渲染器添加到渲染窗口 (vtkRenderWindow) 中。渲染窗口是实际显示 3D 场景的窗口。 - 创建并设置渲染窗口交互器(renderwindow):展示渲染结果的窗口。 
vtkRenderWindowInteractor允许用户与渲染窗口进行交互,例如旋转、缩放或平移视图。 
示例代码
1  | // 创建一个 vtkNamedColors 的实例,使用它来为对象和背景选择颜色。  | 
vtkNamedColors是一个类,提供了对常见颜色名称的访问。例如,它可以让我们用"Tomato"、"CadetBlue"等预定义的颜色名称,而不是手动指定 RGB 值。这里创建了一个colors对象,方便我们在后续代码中选择颜色。
1  | // 现在我们创建一个 vtkConeSource 的实例,并设置它的一些属性。  | 
vtkConeSource是一个源对象,用于生成一个圆锥体的几何数据。通过设置以下参数来控制圆锥的属性:SetHeight(3.0):设置圆锥的高度为 3.0 单位。SetRadius(1.0):设置圆锥的底面半径为 1.0 单位。SetResolution(10):设置圆锥底面的分辨率,即底面多边形的边数。较高的分辨率会使圆锥底面更平滑。
1  | // 在这个例子中,我们通过一个映射器处理对象来终结管道。  | 
vtkPolyDataMapper是一个用于将多边形数据(例如圆锥的几何数据)转换为图形原语的对象。它是 VTK 渲染管线中的重要组件。SetInputConnection(cone->GetOutputPort()):将圆锥源的输出数据连接到映射器的输入端,表示映射器将使用圆锥的数据进行渲染。
1  | // 创建一个演员来表示圆锥体。演员协调映射器的图形原语的渲染。  | 
vtkActor是一个表示可视化对象的核心组件,它将多边形数据通过映射器传递给渲染器。演员将负责场景中对象的可视化表示。SetMapper(coneMapper):将映射器coneMapper与演员coneActor绑定,使得演员可以使用映射器渲染的数据。- 每个演员都有一个 
vtkProperty对象,用于管理它的可视化属性(例如颜色、透明度等)。GetProperty()获取演员的属性对象。SetColor(colors->GetColor3d("MistyRose").GetData())设置演员的颜色为MistyRose(雾玫瑰色)。colors->GetColor3d("MistyRose")返回一个vtkColor3d对象,它表示 MistyRose 颜色的 RGB 值。通过.GetData()方法,实际的 RGB 数据被提取出来并应用到演员的属性上。
 
1  | // 创建渲染器并将演员分配给它。渲染器像一个视口。  | 
vtkNew<vtkRenderer> ren1;:使用vtkNew创建了一个新的渲染器对象ren1。渲染器是 VTK 中的核心组件之一,负责控制场景的绘制,类似于一个视口(viewport)。渲染器会管理显示在窗口中的所有对象,并决定如何绘制它们。ren1->AddActor(coneActor);:将之前创建的演员coneActor添加到渲染器ren1中。演员是负责渲染可视化对象的组件。在这个例子中,演员代表了一个圆锥体对象。渲染器将会根据演员的属性(如颜色、位置等)来绘制它。ren1->SetBackground(colors->GetColor3d("MidnightBlue").GetData());:设置渲染器的背景颜色为 MidnightBlue(午夜蓝)。colors->GetColor3d("MidnightBlue")返回一个vtkColor3d对象,该对象包含 RGB 颜色值,.GetData()方法用于提取实际的 RGB 数据并传递给SetBackground()方法。这使得渲染窗口的背景色变为午夜蓝。
1  | // 最后,我们创建一个渲染窗口,渲染窗口将显示在屏幕上。  | 
vtkNew<vtkRenderWindow> renWin;:创建了一个新的渲染窗口renWin。渲染窗口是一个图形界面窗口,负责显示渲染器中所有的对象。它通常对应于用户看到的图形输出窗口。renWin->AddRenderer(ren1);:将之前创建的渲染器ren1添加到渲染窗口renWin中。通过这个设置,渲染窗口renWin就能够显示渲染器ren1中的图形内容(如圆锥体及其背景色)。renWin->SetSize(300, 300);:设置渲染窗口的大小为 300 像素 x 300 像素。renWin->SetWindowName("Tutorial_Step1");:设置渲染窗口的标题为"Tutorial_Step1"。
1  | // 现在我们循环 360 度,每次渲染圆锥体。  | 
renWin->Render();:负责触发渲染窗口的绘制操作。每次调用Render()方法时,渲染窗口会根据渲染器中的内容更新图形显示。ren1->GetActiveCamera()->Azimuth(1);:通过ren1->GetActiveCamera()获取当前渲染器中正在使用的相机,并调用Azimuth(1)方法让相机绕其垂直轴旋转 1 度。Azimuth()方法用于使相机沿水平方向(围绕 z 轴)旋转指定的角度。
效果

Step2
VTK 使用命令/观察者设计模式。也就是说,观察者会监视任何vtkObject(或子类)可能对其自身调用的特定事件。例如,vtkRenderer在开始渲染时会调用“StartEvent”。这里我们添加了一个观察者,当观察到此事件时,它会调用命令。
与step1的区别主要在于随着圆锥体的旋转,回调函数会打印出当前活动摄像机的三维位置。
示例代码
1  | // 首先包含我们正在使用的 VTK 类所需的头文件。  | 
- 命名空间: 使用匿名命名空间(
namespace {})封装回调函数,确保它仅在当前文件中可见。这是一种避免全局变量命名冲突的好方法。 - vtkMyCallback 类:
vtkMyCallback类继承自vtkCommand,这是 VTK 中处理事件和回调的基类。Execute()方法是回调函数的核心。当事件触发时,该方法会被调用。在这里,它从vtkRenderer获取活动相机的位置并将其打印出来。
 reinterpret_cast: 使用reinterpret_cast将传递给回调函数的caller对象转换为vtkRenderer*类型。caller是触发回调的对象(在此为vtkRenderer),通过这种方式获取相机位置。- 打印相机位置: 使用 
renderer->GetActiveCamera()->GetPosition()获取相机的 3D 坐标(x, y, z),并打印到控制台。 
1  | vtkNew<vtkNamedColors> colors;  | 
- 这部分代码和step1中的完全相同,除了多了一行
ren1->ResetCamera();,用于重置相机的位置,使得圆锥体正确显示在视口中。ResetCamera()会根据场景中的对象自动调整摄像机位置,确保它们可以被清晰地看到。 
1  | // Here is where we setup the observer.  | 
vtkNew<vtkMyCallback> mo1;:创建一个vtkMyCallback类型的回调函数对象mo1。ren1->AddObserver(vtkCommand::StartEvent, mo1);:将回调函数mo1添加到渲染器ren1上,并监听StartEvent事件。vtkCommand::StartEvent是 VTK 的一个事件类型,当渲染开始时会触发该事件,从而调用mo1中的Execute()方法。
1  | // 现在我们循环 360 度,每次渲染圆锥体。  | 
- 与step1类似
 
效果

与step1不同的是,多进行了一段屏幕输出(回调函数),共计输出了360行。
step3
此示例演示如何在渲染窗口内使用多个渲染器。(创建了两个不同的渲染器,显示相同的圆锥体对象在不同的视口中)
示例代码
1  | vtkNew<vtkNamedColors> colors;  | 
- 和之前完全一致。
 
1  | // 创建两个渲染器并将演员添加到其中。渲染器将演员渲染到 vtkRenderWindow 内的一个视口中。  | 
创建一个渲染器
ren1,并将圆锥体的演员coneActor添加到其中。设置背景颜色为
RoyalBlue。SetViewport(0.0, 0.0, 0.5, 1.0):设置渲染器的视口(即渲染区域)。这里,视口的范围是(0.0, 0.0)到(0.5, 1.0),即占据窗口的左半部分。
创建另一个渲染器
ren2,并添加相同的演员coneActor。- 设置背景颜色为 
DodgerBlue。 SetViewport(0.5, 0.0, 1.0, 1.0):设置第二个渲染器的视口为右半部分,覆盖窗口的右半部分。
- 设置背景颜色为 
 
1  | vtkNew<vtkRenderWindow> renWin;  | 
- 与之前类似
 
效果

step4
此示例演示了如何创建多个参与者以及如何操纵他们的属性和转换。
示例代码
1  | vtkNew<vtkNamedColors> colors;  | 
- 与之前相同
 
1  | // 创建一个演员来表示第一个圆锥。演员的属性被修改,以赋予它不同的表面属性。  | 
创建一个
vtkActor对象,并将圆锥的映射器coneMapper设置为该演员的映射器。coneActor->GetProperty()->SetColor(0.2, 0.63, 0.79)设置演员的颜色(RGB 值为 0.2, 0.63, 0.79)。设置演员的材质属性:漫反射强度为 0.7,镜面反射强度为 0.4,镜面反射高光强度为 20。这些属性影响演员在渲染时的外观效果。
创建了一个新的
vtkProperty对象,设置其颜色为"Tomato",漫反射强度为 0.7,镜面反射强度为 0.4,镜面反射高光强度为 20。创建第二个演员
coneActor2,并为其设置与第一个演员相同的映射器coneMapper。设置
coneActor2的颜色为"LightSeaGreen",并将之前创建的property设置为该演员的材质属性。将第二个演员
coneActor2的位置设置为(0, 2, 0),即在 Y 轴上将其上移 2 个单位。
两个问题:
1.示例代码中对actor2的颜色设置部分存在冗余代码
1  | property->SetColor(colors->GetColor3d("Tomato").GetData());  | 
最终的颜色是Tomato,第二行代码冗余。
2.只设置actor2的位置,没有设置actor的位置。
coneActor2->SetPosition(0, 2, 0);: 这行代码设置了coneActor2的位置。SetPosition会将该演员的几何位置设置为 (0, 2, 0),即沿 Y 轴偏移 2 单位。- 默认情况下,如果没有特别设置位置,演员会处于原点 
(0, 0, 0)。因此,coneActor没有调用SetPosition,它会保持在默认位置。 - 在 VTK 中,演员的坐标是相对于渲染器的原点的。通常,如果你有多个演员,并且希望它们不重叠,可以为每个演员设置不同的位置。在这段代码中,
coneActor2被显式地放置到(0, 2, 0),而coneActor使用默认位置(0, 0, 0)。 

step5
  引入交互的概念,定义了一种不同于默认的交互风格。(通过 vtkInteractorStyleTrackballCamera实现)
示例代码
1  | vtkNew<vtkNamedColors> colors;  | 
- 与之前一样
 
1  | // vtkRenderWindowInteractor 类用于监视 vtkRenderWindow 中的事件(例如,按键、鼠标事件)。  | 
- 创建了一个 
vtkRenderWindowInteractor对象iren,它使得用户能够与渲染窗口进行交互。SetRenderWindow()将窗口与交互器关联。 - 创建了一个 
vtkInteractorStyleTrackballCamera对象style,这是一个常用的交互样式,可以通过鼠标拖动来旋转、平移和缩放视图。并将交互器样式设置为style,使得用户可以通过鼠标控制视角。 iren->Initialize()初始化交互器。iren->Start()启动交互,程序将在此处等待用户交互。
效果

用户可以通过鼠标拖动查看不同视角下的模型。
step6
此示例介绍了 3D 小部件。3D 小部件利用了前面介绍的事件/观察者设计模式。它们通常在场景中具有特定的表示,可以使用鼠标和键盘进行交互选择和操作。当操作小部件时,它们依次调用 StartInteractionEvent、InteractionEvent 和 EndInteractionEvent 等事件,这些事件可用于操作小部件所嵌入的场景。3D 小部件在上一个示例中设置的事件循环上下文中工作。
示例代码
1  | namespace {  | 
void Execute(vtkObject* caller, unsigned long, void*)Execute是重写自vtkCommand的虚函数。当事件触发时,这个方法会被调用。在这个回调函数中,具体的操作是对vtkBoxWidget进行变换的获取和设置。vtkObject* caller:caller是触发事件的对象。在这个回调中,它将被转换为vtkBoxWidget*类型。vtkBoxWidget是一个交互式的控件,通常用于控制对象的变换(例如移动、旋转、缩放等)。
unsigned long和void*:- 这两个参数通常用于处理事件的 ID 和附加数据,但在这个回调函数中并没有被使用。
 
vtkNew<vtkTransform> t;- 创建了一个新的 
vtkTransform对象t,该对象用于存储 3D 变换(如位置、旋转、缩放)。vtkTransform是 VTK 用于表示几何变换(如平移、旋转、缩放等)的类。 
- 创建了一个新的 
 auto widget = reinterpret_cast<vtkBoxWidget*>(caller);- 通过 
reinterpret_cast将caller转换为vtkBoxWidget*类型。caller是触发事件的对象,我们期望它是一个vtkBoxWidget,因此需要进行类型转换。 
- 通过 
 widget->GetTransform(t);- 调用 
vtkBoxWidget的GetTransform方法,将当前vtkBoxWidget的变换信息(例如位置、旋转、缩放)存储到t变量中。 
- 调用 
 widget->GetProp3D()->SetUserTransform(t);- 获取 
vtkBoxWidget对象的 3D 属性(GetProp3D()),然后调用SetUserTransform(t),将之前获取的变换应用到控件的 3D 属性上。 SetUserTransform方法允许用户在现有的控件基础上应用额外的变换。
- 获取 
 
vtkBoxWidget是一个用于交互式操作的 VTK 小部件,它允许用户通过鼠标拖动和操作一个 3D 的盒子(或矩形区域),来进行模型的变换。vtkBoxWidget具有与这些操作相关的事件和回调机制,通过监听这些事件并响应,可以在vtkActor上实现这些变换。vtkTransform是 VTK 中用于存储和应用变换(如平移、旋转、缩放等)的类。在代码中,我们使用vtkTransform来存储和应用vtkBoxWidget获取到的变换。widget->GetTransform(t);这行代码获取
vtkBoxWidget当前的变换,并将其存储到vtkTransform对象t中。vtkBoxWidget内部会跟踪用户通过交互对物体所做的变换(平移、缩放、旋转等)。GetTransform会将这些变换信息提取出来。widget->GetProp3D()->SetUserTransform(t);最后,通过
widget->GetProp3D()获取与vtkBoxWidget关联的vtkProp3D对象(即需要变换的 3D 图形对象)。然后调用SetUserTransform(t)方法,应用之前从vtkBoxWidget中获取到的变换。SetUserTransform允许将vtkTransform应用到 3D 对象上,使得对象的变换(平移、旋转、缩放)生效。
1  | vtkNew<vtkNamedColors> colors;  | 
- 与之前一样
 
1  | vtkNew<vtkBoxWidget> boxWidget;  | 
vtkBoxWidget是 VTK 中一个交互式小部件,允许用户通过拖动一个 3D 方框来变换场景中的对象。用户可以通过拖动盒子的边、角来平移、旋转和缩放物体。boxWidget->SetInteractor(iren);使得vtkBoxWidget能够与交互器iren关联,从而能够响应用户的鼠标输入。boxWidget->SetPlaceFactor(1.25);设置盒子小部件的缩放因子。这个因子影响了盒子的尺寸,通常是通过调整vtkBoxWidget形成的盒子与场景中物体的相对比例来控制。1.25的值表示盒子在默认情况下稍微大于物体本身。boxWidget->GetOutlineProperty()->SetColor(colors->GetColor3d("Gold").GetData());设置盒子轮廓的颜色为 “Gold”(金色)。GetOutlineProperty()获取盒子的属性,之后设置颜色。boxWidget->SetProp3D(coneActor);将coneActor设置为vtkBoxWidget的目标物体,意味着用户将通过拖动盒子来变换这个圆锥体 (coneActor)。boxWidget->PlaceWidget();调用此方法后,vtkBoxWidget会根据coneActor的边界自动设置盒子的位置和大小,使得盒子能够完全包围住物体。这样,用户就可以通过调整盒子的大小和位置来操作圆锥体。vtkMyCallback是前面我们分析过的自定义回调类,它会在用户与vtkBoxWidget交互时被触发。回调函数Execute会在盒子的小部件与用户交互时被调用,用于处理变换(平移、旋转、缩放)。boxWidget->AddObserver(vtkCommand::InteractionEvent, callback);将回调函数callback注册到vtkBoxWidget上。当用户进行交互时(如拖动、缩放、旋转盒子),vtkCommand::InteractionEvent事件会触发,进而调用vtkMyCallback::Execute方法,更新coneActor的变换。boxWidget->On();启用vtkBoxWidget,使得它可以响应用户的交互。此时用户可以通过鼠标操作盒子,改变coneActor的变换。
效果
