AI 协作日志

学生 Web 实验作品平台

学号:202412211401032 · 来源:ai-log.md

# 实验三 AI协作与核验记录

课程:计算机图形学 · 实验编号:实验3
学号:202412211401032 · 姓名:张智豪

AI工具:Trae CN 内置 AI 编程助手(模型:Kimi-K3),用于讨论矩阵次序、生成与核对代码、驱动浏览器自动化测试。

## 协作1:矩阵与变换次序(Task B)

- 我的目标和预先预测:
  目标是把 `Rz(θ)·T(C)` 与 `T(C)·Rz(θ)` 的差别落实到代码,并让 task-b 页面右侧 5 项数值测试全绿。
  我的预测:取 `C=(0.50,0.25)`、θ=90°。因为本实验统一列向量、矩阵右侧先执行——
  - `R·T`:先平移到 C 再绕世界原点转,新的平移分量 = `R·C = (-0.25, 0.50, 0)`,正方形"搬家"→ 公转;
  - `T·R`:先自转再平移,平移分量仍是 `(0.50, 0.25, 0)`,正方形中心不动 → 自转。
  另预测数值测试:`T(0.3,-0.2,0)·(1,0,0,1)=(1.3,-0.2,0,1)`;`S(2)·(1,0,0,1)=(2,0,0,1)`;`Rz(90°)·(1,0,0,1)=(0,1,0,1)`;`Ry(90°)·(1,0,0,1)=(0,0,-1,1)`;平移作用于方向向量 `(1,0,0,0)` 不变。
- 关键提示词(原文):
  "实现 js/transforms.js 的 S 缩放矩阵与 R 绕 X/Y/Z 轴旋转矩阵(公共库是 mat4 教学子集,提供 fromScaling/fromXRotation/fromYRotation/fromZRotation),并实现 B-05:pivot=world 用 R·T,pivot=self 用 T·R。"
- AI建议摘要:
  AI 指出公共库矩阵是列主序、列向量约定,`fromZRotation` 首列是 `(cosθ, sinθ, 0)`,故 `Rz(90°)·(1,0,0)=(0,1,0)` 与教材一致;`fromYRotation` 首列是 `(cosθ,0,-sinθ)`,故 `Ry(90°)·(1,0,0)=(0,0,-1)`。组装 Model 时 `multiply(a,b)` 表示 `a·b`,右项先作用于顶点,因此公转写 `multiply(rot, T(...c))`,自转写 `multiply(T(...c), rot)`。
- 我的计算或测试方法:
  1. 打开 task-b.html 读"矩阵数值检验"区 5 项的 ✓/✗ 与实际数值;
  2. 在页面上设 θ=90°、中心 (0.50,0.25),分别切换"世界原点·R×T"与"对象中心·T×R",读取 `#matrix-output` 按行打印的矩阵;
  3. 再用浏览器自动化对平移(ΔX=0.3)、缩放(s=2)、四面体 Y 轴 90° 各测一次。
- 实际结果与证据:
  - 5 项数值测试全部 ✓:`(1.3,-0.2,0,1)`、`(2,0,0,1)`、`(0,1,0,1)`、`(0,0,-1,1)`、`(1,0,0,0)`,与预测一致;
  - world 模式矩阵平移列为 `(-0.250, 0.500, 0)`,self 模式平移列为 `(0.500, 0.250, 0)`,与预测完全一致;
  - 平移矩阵平移列 `(0.800, 0.250, 0)`(0.5+0.3);缩放矩阵对角 `(2,2,2)` 且平移列不变;四面体 `Ry(90°)` 第一行≈`(0,0,1)`、第三行≈`(-1,0,0)`。控制台无报错。
- 采纳、拒绝或修正的结论:
  全部采纳。矩阵作用于列向量时右侧先执行,`R·T ≠ T·R` 的差别直接体现在平移分量上:自转矩阵的平移列恒为 C,公转矩阵的平移列为 `R·C`(随角度变化)。

## 协作2:故障诊断与修复(Task C,有意制造后修复的 Bug Hunt)

- 错误现象、触发步骤:
  为验证"公转/自转次序"的判据并留档,我在 `js/transforms.js` 的 `modelFor()` 旋转分支中有意把 world 公转写成错误次序 `multiply(T(...c), rot)`(即 T·R)。打开 task-c.html 后:正方形不再绕画布中心运动,只在 (0.53,0.32) 原地打转;圆、三角形、四面体均正常。
- 我先检查了什么:
  先排除动画时间、速度、暂停逻辑(`obj.elapsed` 在增长,其它对象正常),把范围缩到 modelFor 的 rotate 分支;再用页面调试接口读取正方形 Model 矩阵平移分量随时间的变化。
- 关键提示词(原文):
  "task-c 的正方形 pivot=world 时平移分量应该随时间变化;若 Model 矩阵平移列恒等于 C,说明写成了 T·R。用 CG3TEST.getMatrices()[2].slice(12,15) 在两个相隔 1.5 秒的时刻各取一次来验证。"
- AI列出的候选原因:
  ①矩阵次序写反(T·R 与 R·T 混淆);②angle 用了度没转弧度(那样会表现为转速异常而非不公转);③每帧重建对象把 elapsed 清零;④绘制时没遍历到该对象。
- 我逐项测试的结果:
  用 `CG3TEST.getMatrices()[2].slice(12,15)` 在 t₁ 与 t₂(相隔约 1.5 s)两次采样:
  - 出错时两次均为 `[0.530, 0.320, 0]` —— 平移恒定,证实是次序错误(候选①),排除②③④(elapsed 在增长、其它对象正常说明时间和遍历都没问题);
  - 修复为 `multiply(rot, T(...c))` 后复测:t₁=`[-0.093, 0.612, 0]`、t₂=`[0.228, -0.576, 0]`,平移随时间变化,且轨迹半径 `sqrt(0.53²+0.32²)≈0.619` 不变,与 45°/s 公转吻合。
- 真正原因、修改位置和复测结论:
  真正原因:`js/transforms.js` modelFor 旋转分支的乘法次序。修改位置即该分支:`pivot==='world'` 用 `multiply(rot,T(...c))`(R·T 公转),`pivot==='self'` 用 `multiply(T(...c),rot)`(T·R 自转)。复测:task-c 正方形恢复公转、四面体自转正常,页面控制台无错误。该错误随后已改回正确版本并保留在提交代码中。

## 协作3:方案比较与实现核验(Task E,PNG 截图)

- 待解决的具体设计问题:
  WebGL 默认在合成后清空绘制缓冲,直接 `canvas.toBlob()` 可能得到空白/黑色图片。需要选择可靠的截图方案。
- 关键提示词(原文):
  "Task E 要保存当前 WebGL 画布为 PNG。比较两种方案:A. getContext 时设 preserveDrawingBuffer:true,截图前主动重绘再 toBlob;B. 不保留缓冲,只在截图回调里同步重绘+toDataURL。分析时间成本、正确性和可维护性,并实测验证。"
- 两种方案及取舍依据:
  - 方案 A:`preserveDrawingBuffer:true` 让缓冲在合成后仍保留,截图时先 `this.draw()` 再 `toBlob`。优点是任何时候截图都可靠、代码简单、本实验场景性能损失可忽略;缺点是浏览器禁用了一些缓冲复用优化(大场景才有感)。
  - 方案 B:不保留缓冲,必须保证重绘与读像素在同一任务内同步完成(`toDataURL` 同步取值)。优点是理论性能最好;缺点是 `toBlob` 是异步的、时序容易踩坑,一旦次序出错就是空白图,可维护性差。
  取舍:本框架已在 `graphics.js` 创建上下文时设置 `preserveDrawingBuffer:true`,方案 A 与现有结构最契合、正确性最容易保证,故选 A。
- 我最终采用的实现:
  `savePNG()` 中先 `this.draw()` 主动重绘,再 `canvas.toBlob(cb,'image/png')`,回调内检查 Blob 非空后用 `URL.createObjectURL` + 临时 `<a download>` 触发下载(文件名 `实验3_画布_时间.png`),随后 `remove()` 并 `revokeObjectURL` 清理。
- 测试与反思:
  在 task-e.html 实测:添加对象 → 改画布为 960×540、背景 #fffbe6 → 点击"保存PNG截图",状态栏提示"已保存PNG截图:960×540像素";下载的 PNG 用看图软件打开,尺寸与 Canvas 内部像素一致、包含背景色与全部图形。方案 A 一次通过。反思:截图正确性的关键不在 toBlob 用法,而在"读缓冲时缓冲里确实是本帧画面"——主动重绘 + 保留缓冲是最稳的组合。

## 其他使用AI的记录(如有)

- 工具与用途:同一 AI 助手用于按 `README-TODO.md` 索引完成 18 个 TODO 的代码填充,并用浏览器自动化对 task-a~task-e 做回归测试(四种形状显示、动画数值范围、暂停/继续/速度、鼠标点击坐标 (400,300)≈(0,0) 与 (200,150)≈(-0.667,+0.5)、参数快照隔离、960×540 下中心点击仍为 (0,0)、清空后计数归零可继续添加)。
- 关键提示词(原文):"按要求完成实验(实验三 WebGL 变换,补全 18 个 TODO 并逐项实测)"。
- 处理说明和验证:所有 AI 生成的代码均经本人逐段审阅(矩阵次序、度/弧度换算、dt 限幅 0.1 s、暂停不累加 elapsed),并在浏览器中逐页核验;Task C 的次序 Bug 为本人有意注入、复现、修复并复测,过程见协作2。