第 1 阶段练习与参考答案
按教程目录完成第 1–4 章后,再做这些练习。请先独立修改阶段示例,观察浏览器结果,再看每题的参考答案。
练习 1:辨认改动属于哪一层
依次进行以下修改,记录屏幕变化,并判断数据是否被重建:
- 把 <code>sphereSource</code> 的 <code>thetaResolution</code> 和 <code>phiResolution</code> 都改为 <code>8</code>。
- 调用 <code>actor.getProperty().setColor(0.2, 0.8, 0.4)</code>。
- 在添加 Actor 后调用 <code>actor.setPosition(1, 0, 0)</code>,再重置相机。
参考答案
第 1 项改变 Source 产生的点和多边形,属于数据层。第 2 项只改变表面外观,不重建数据。第 3 项改变 Actor 在场景中的变换;Source 输出的局部点坐标仍保持原样。后两项都可能改变屏幕画面,但不代表 <code>vtkPolyData</code> 内容被修改。
练习 2:增加一个蓝色立方体
要求保留橙色球体,新建立方体的 Source、Mapper 和 Actor,把立方体放到球体右侧,并让相机看到两个对象。
参考答案
在 <code>src/main.js</code> 的导入区增加:
import vtkCubeSource
from "@kitware/vtk.js/Filters/Sources/CubeSource";
在原有 <code>renderer.resetCamera()</code> 之前增加:
const cubeSource = vtkCubeSource.newInstance({
xLength: 0.7,
yLength: 0.7,
zLength: 0.7,
});
const cubeMapper = vtkMapper.newInstance();
cubeMapper.setInputConnection(cubeSource.getOutputPort());
const cubeActor = vtkActor.newInstance();
cubeActor.setMapper(cubeMapper);
cubeActor.setPosition(1.6, 0, 0);
cubeActor.getProperty().setColor(0.2, 0.7, 0.9);
renderer.addActor(cubeActor);
让原有 <code>renderer.resetCamera()</code> 与 <code>renderWindow.render()</code> 保持在两个 Actor 添加之后。立方体数据仍围绕其局部原点生成,显示位置由 <code>cubeActor</code> 决定。
练习 3:画出两个关系
不看正文,分别画出:
- 球体数据到屏幕的连接顺序。
- Actor 与相机分别由哪个对象管理。
然后解释 <code>setInputConnection</code>、<code>setMapper</code> 和 <code>addActor</code> 是否是同一种连接。
参考答案
数据与显示顺序为:
vtkSphereSource → vtkMapper → vtkActor → vtkRenderer → vtkRenderWindow
其中 <code>setInputConnection</code> 把 Mapper 接到 Source 的输出端口,属于数据处理管线;<code>setMapper</code> 指定 Actor 使用哪个 Mapper;<code>addActor</code> 把可见对象加入 Renderer。相机也由 Renderer 管理,示例通过 <code>renderer.resetCamera()</code> 重新取景。
练习 4:定位空白画面
假设背景颜色正常显示,但球体消失。写出你会检查的至少四项,而不是一开始就修改相机参数。
参考答案
可以按以下顺序检查:
- Source 是否创建,是否能产生 <code>vtkPolyData</code>。
- Mapper 是否通过 <code>setInputConnection</code> 或 <code>setInputData</code> 收到数据。
- Actor 是否通过 <code>setMapper</code> 持有 Mapper,且处于可见状态。
- Renderer 是否通过 <code>addActor</code> 收到 Actor。
- 添加 Actor 后是否调用 <code>resetCamera()</code>,是否触发 <code>renderWindow.render()</code>。
- 浏览器控制台是否报告 WebGL 或模块加载错误。
这份清单分层排查数据、映射、场景和环境,比随机调节相机更容易发现根因。