第 13 章:vtkActor 与 vtkProperty——放置和显示一个表面
学习目标
你已知道 Mapper 怎样接收数据。本章学习它后面的两个对象:vtkActor 把表面放进场景,vtkProperty 控制表面外观。读完后,你应该能区分修改几何点坐标、Actor 变换和 Property 外观;也能正确解释为什么设置 setColor() 后画面仍由标量颜色控制。
13.1 Actor 在场景中的位置
基本连接是:
const actor = vtkActor.newInstance();
actor.setMapper(mapper);
renderer.addActor(actor);
Actor 与 Three.js Mesh 有相似之处:它是可见场景对象,可以平移、旋转、缩放,也有可见性状态。但 vtk.js 把数据输入和标量选择留在 Mapper,把表面外观集中到 Actor 的 vtkProperty。因此不能只凭 Three.js 的 geometry + material 类比跳过中间层。
同一份 vtkPolyData 可以由多个 Mapper、Actor 显示。第 3 阶段示例就用两个 Mapper 指向同一数据,左侧显示 Point Data,右侧显示 Cell Data。反过来,多个 Actor 也可以共享一个 Mapper,分别摆在不同位置;若它们共享同一个 Mapper,改变 Mapper 的数组选择会同时影响这些 Actor。要让它们独立着色,就分别创建 Mapper。
13.2 变换不改写数据点
Actor 常用的空间变换包括:
actor.setPosition(2, 0, 0);
actor.setOrientation(0, 30, 0);
actor.setScale(1, 1, 1.5);
renderWindow.render();
这些操作改变的是场景中的放置方式。polyData.getPoints().getPoint(0) 仍返回原来的数据坐标。若想真正修改网格,应改 vtkPoints 或上游算法;若只是摆放副本,应改 Actor。对后续数值分析、拾取和导出而言,这个区别十分重要。
actor.setVisibility(false) 可临时隐藏对象。隐藏不是删除数据,也不等于从 Renderer 移除 Actor。要让相机重新适应新位置或新可见内容,可以调用 renderer.resetCamera(),但频繁调节外观时通常不必每次重置相机。
13.3 获取 vtkProperty
Actor 通过 actor.getProperty() 暴露表面属性:
const property = actor.getProperty();
property.setColor(0.92, 0.72, 0.28);
property.setOpacity(0.7);
property.setEdgeVisibility(true);
property.setEdgeColor(0.12, 0.16, 0.20);
颜色分量使用 0–1 范围,不是 0–255。setOpacity(1) 为不透明,setOpacity(0) 为完全透明。透明对象的实际混合结果还受深度和渲染顺序影响;本章先只在单个表面上观察它,复杂的多层透明显示留待具体项目中处理。
setEdgeVisibility(true) 是在表面上显示网格边界;setRepresentationToWireframe() 则把表示方式改成线框。它们外观看似接近,语义不同:前者仍有填充表面,后者主要显示边线。第 4 阶段示例的“线框”开关使用后者。
13.4 表示方式、光照与裁剪面
三种常见表示方式:
property.setRepresentationToSurface(); // 填充表面
property.setRepresentationToWireframe(); // 线框
property.setRepresentationToPoints(); // 点
这些都不会改变原始 vtkPolyData。一个三角形单元仍是同一个单元,只是绘制方式不同。网格过密时,线框可能在屏幕上重叠,看不清拓扑;可先换小网格检查。
默认表面通常参与光照。property.setLighting(false) 可使单色或标量颜色更直接地显示,而 setLighting(true) 恢复受光照影响的外观。setBackfaceCulling(true) 会剔除背向相机的面;如果面法向或点序与预期相反,表面可能消失。对初学者,先保持默认关闭背面剔除,更容易排除数据问题。
Three.js 中你熟悉的“光照、面材质、相机”概念在这里仍适用。vtk.js 的额外难点是:同一可见表面还可能由科学标量着色,颜色因此有数据意义,而不仅是美术材质。
13.5 为什么 setColor 看起来无效
第 4 阶段示例给 Actor 设置了金色单色:
actor.getProperty().setColor(0.92, 0.72, 0.28);
示例初始仍显示蓝到红的标量颜色,因为 Mapper 正在使用 Temperature 数组。切换“Actor 单色”会执行:
mapper.setScalarVisibility(false);
renderWindow.render();
现在才能直接观察 Property 的单色。不要通过删除 Point Data 来测试 Actor 颜色;关掉标量可见性即可,数据仍在原处。以后再打开标量可见性并选择数组,画面就会重新表达数值。
13.6 调试顺序
如果只看到背景:先检查 Actor 是否在 Renderer 中及相机是否看到它,再检查 Mapper 输入。若有几何但外观错误:查 Mapper 的标量状态、Property 的表示方式和不透明度。若线框形状正确、填充却消失,查正反面剔除及点顺序。这样逐层定位比一次更改多个设置更容易找到原因。
本章小结
Actor 管可见对象的放置与显示状态,Property 管表面的颜色、透明度、边线和表示方式。Mapper 的标量颜色可能覆盖你期望的单色结果。下一章深入说明多个科学数组怎样经过颜色映射进入表面画面。