第 1 阶段练习与参考答案

按教程目录完成第 1–4 章后,再做这些练习。请先独立修改阶段示例,观察浏览器结果,再看每题的参考答案。

练习 1:辨认改动属于哪一层

依次进行以下修改,记录屏幕变化,并判断数据是否被重建:

  1. 把 <code>sphereSource</code> 的 <code>thetaResolution</code> 和 <code>phiResolution</code> 都改为 <code>8</code>。
  2. 调用 <code>actor.getProperty().setColor(0.2, 0.8, 0.4)</code>。
  3. 在添加 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:画出两个关系

不看正文,分别画出:

  1. 球体数据到屏幕的连接顺序。
  2. 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:定位空白画面

假设背景颜色正常显示,但球体消失。写出你会检查的至少四项,而不是一开始就修改相机参数。

参考答案

可以按以下顺序检查:

  1. Source 是否创建,是否能产生 <code>vtkPolyData</code>。
  2. Mapper 是否通过 <code>setInputConnection</code> 或 <code>setInputData</code> 收到数据。
  3. Actor 是否通过 <code>setMapper</code> 持有 Mapper,且处于可见状态。
  4. Renderer 是否通过 <code>addActor</code> 收到 Actor。
  5. 添加 Actor 后是否调用 <code>resetCamera()</code>,是否触发 <code>renderWindow.render()</code>。
  6. 浏览器控制台是否报告 WebGL 或模块加载错误。

这份清单分层排查数据、映射、场景和环境,比随机调节相机更容易发现根因。