第 1 章:vtk.js 在解决什么问题

学习目标

读完本章,你应该能区分数据与显示结果,知道 vtk.js 为什么采用数据处理管线,并能解释为什么“vtk.js 就是做体渲染的 Three.js”这个说法不准确。

1.1 从一个具体问题出发

假设你拿到一份头部 CT。文件中最核心的内容不是“头骨模型”,而是许多空间位置上的测量值:每个采样位置有一个数值,采样位置之间有确定的物理间距。你可能想看某一层切片、让特定数值范围显现为半透明结构,或者提取一个三角形表面。

这些图像都可以从同一份数据产生,但它们不是数据本身。若把“读取 CT”和“画出一个模型”视为同一件事,就很难理解 vtk.js 为什么需要 Reader、Filter、Mapper 等多个对象。

再看一份流体仿真结果。它可能包含网格、每个位置的压力,以及每个位置的三维速度。你可以把压力画成表面颜色,也可以选取一个截面,还可以根据速度计算新的量。这里既有空间结构,也有附着在结构上的数值。

数据所描述的内容 可能的显示方式
点和多边形组成的地形,点上有高度值 三角形表面、按高度着色、等高线
规则三维网格,每处有 CT 值 切片、体渲染、等值面
仿真网格,每处有压力和速度 按压力着色、截面、箭头或流线

因此,科学可视化通常要连续回答三个问题:

  1. 数据是什么? 它在空间中怎样排列,数值属于哪个位置?
  2. 要怎样处理? 是否需要切片、裁剪、计算或提取等值面?
  3. 要怎样显示? 使用表面、二维切片、体渲染还是其他表示?

vtk.js 的设计让这三个问题能够由不同对象处理。

1.2 vtk.js 与 VTK 的关系

VTK 是长期用于科学可视化的工具体系。vtk.js 将许多 VTK 的数据模型、管线和渲染概念带到 JavaScript 与浏览器中。因此,你会看到 <code>vtkPolyData</code>、<code>vtkImageData</code>、Mapper、Actor 等带有 VTK 传统的名称。

vtk.js 并非完整 C++ VTK 的逐类翻译。学习时应以所用 vtk.js 版本的实际 API为准:相似的类名有助于理解概念,但不能保证 C++ VTK 的每个算法或方法在浏览器中都存在。本教程固定使用 <code>@kitware/vtk.js 37.4.2</code>,并为示例代码提供可运行项目。

1.3 vtk.js 也会画三角形

你熟悉的 Three.js 场景通常包含显式的顶点和三角形。vtk.js 的 <code>vtkPolyData</code> 同样可以保存点与多边形;相应 Mapper 最终仍会利用 GPU 绘制表面。因此,它们在表面最终被光栅化这一层面并不神秘。

区别主要发生在更早的步骤。vtk.js 不要求你一开始就把所有数据想成一个待绘制的 Mesh。一份数据可以经过 Filter 转换,再以不同方式显示;数据对象也可以同时保存多个标量或向量数组。例如,仿真网格既能根据温度着色,也能根据压力着色,而点与单元的空间结构不必因此重建。

vtk.js 也支持体数据的显示。常见的体渲染方法让视线穿过三维采样场,沿途读取数值并累积颜色与不透明度。这里不需要先为每一个体素构造一个小立方体;详细原理放在第 16 章。

1.4 数据结构为什么带有“科学语义”

在普通网格渲染中,一个顶点上的数组可能表示位置、法线或纹理坐标。科学数据还要明确记录数值属于什么实体。例如:

这种归属会影响插值和显示。点上的数值通常可以跨单元平滑变化;单元上的数值可以保持分块常量。数组里即使有相同的数字,只要关联位置不同,图像就可能不同。第 8–10 章会用手工数据验证这一点。

对于规则三维数据,除了数值数组,还需要知道维度、起点、采样间距和方向。数组下标 <code>(i, j, k)</code> 只有结合这些信息,才对应到实际空间中的位置。忽略间距,就可能把一份层间距离很大的医学影像画得像被压扁或拉长。

1.5 什么时候使用 vtk.js

当任务围绕空间数据、标量或向量场、切片、等值面、裁剪、体渲染及数值查询展开时,vtk.js 提供了适合这些任务的数据对象和算法管线。当任务主要是自由布置场景物体、动画与通用三维交互时,你已有的 Three.js 经验往往更直接。两种库也可以在同一个产品中承担不同的功能。

选择工具之前,先问“我最核心的输入是什么”。若核心输入是一份需要解释和探索的空间数据,就应该优先研究 vtk.js 怎样表示这份数据,而不是先找一个与 Three.js <code>Mesh</code> 同名同义的类。

本章小结

vtk.js 的学习主线是 空间数据 → 数据处理 → 显示方式。表面渲染与体渲染都是这条主线的结果;它们不是对 vtk.js 的完整定义。接下来,我们用你熟悉的 Three.js 对象建立第一张概念地图,同时标清每个类比的适用范围。

参考资料