AI 协作日志

学生 Web 实验作品平台

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

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

AI工具:豆包(Doubao)PC客户端 · 对话式协助 + 浏览器实测核验(本记录基于本次完成实验的真实协作过程整理;提交前请按个人实际情况核对“我的预测”与测试证据)

---

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

- **我的目标和预先预测**:
  目标:让同一个正方形在初始中心 `C=(0.50, 0.25)` 下分别表现“绕世界原点公转”和“绕自身中心自转”。
  预测:列向量约定下右侧矩阵先作用。`R·T(C)` 会先把正方形平移到 C,再绕世界原点旋转,所以正方形中心的位置列会被旋转矩阵改变(轨迹是绕原点的圆弧);`T(C)·R` 会先绕局部原点旋转、再平移到 C,位置列应保持 `(0.50, 0.25)` 不变。
- **关键提示词(原文)**:
  “Task B 里正方形初始中心 (0.50, 0.25),pivot 选 world 和 self 时 Model 矩阵的乘法次序分别应该怎么写?列向量下哪一边先执行?角度从度转弧度在哪里转?”
- **AI建议摘要**:
  ① 列向量时右侧矩阵先作用于顶点;② world(公转)用 `M = R·T(C)`,self(自转)用 `M = T(C)·R`;③ 三角函数前用 `deg2rad()` 把“度/秒·秒”的角度换成弧度,避免方向或大小错误。
- **我的计算或测试方法**:
  手算 `Rz(45°)·T(0.50,0.25)` 的位置列:
  `tx = 0.50·cos45° − 0.25·sin45° ≈ 0.177`,`ty = 0.50·sin45° + 0.25·cos45° ≈ 0.530`;
  自转则应保持 `(0.50, 0.25)`。另用 Node 自测脚本(加载教材离线 `gl-matrix.js` 子集 + `transforms.js`)对 5 项数值测试逐一断言。
- **实际结果与证据**:
  - `task-b.html` 页面 matrix-output:world 模式位置列显示 `(0.177, 0.530)`,self 模式显示 `(0.500, 0.250)`,与手算完全一致;
  - 页面“矩阵数值检验”5 项全部显示 ✓:平移 `(1.3,-0.2,0,1)`、缩放 `(2,0,0,1)`、Z 轴 +90° `(0,1,0,1)`、Y 轴 +90° `(0,0,-1,1)`、w=0 向量平移不变 `(1,0,0,0)`;
  - Node 自测 15 项断言全部 PASS(含三角波端点 0/0.5/1/0.5/0)。
- **采纳、拒绝或修正的结论**:
  采纳 AI 建议的矩阵次序与弧度换算。页面实测与手算一致,说明 `R·T(C)`(公转)与 `T(C)·R`(自转)的差别就是“先平移再旋转”与“先旋转再平移”的次序差别,被 AI 建议验证后直接采用。

---

## 协作2:故障诊断与修复 —— 暂停后动画仍在走(Task C,4分)

- **错误现象、触发步骤**:
  现象:`task-c.html` 点击“暂停动画”,状态显示“已暂停”,但右侧实时数值仍在变化(圆形缩放从 `1.72×` 变为 `1.37×`,三角形位移从 `-0.163` 变为 `0.291`)。
  触发步骤:运行页面 → 等待 1 秒 → 点击暂停 → 再等 1 秒 → 观察 motion-debug 数值。
- **我先检查了什么**:
  ① 是否存在重复的 `requestAnimationFrame` 循环(在 App 构造中只启动一次,确认没有);② `tick()` 里 `dt` 是否受 `this.running` 与 `this.globalSpeed` 约束;③ 暂停期间 `lastMs` 是否仍正常更新(影响恢复时是否突跳)。
- **关键提示词(原文)**:
  “暂停按钮状态已经变成已暂停,但 motion-debug 的数值还在动。请列出可能原因和逐项排查办法,重点看 dt 的计算位置。”
- **AI列出的候选原因**:
  ① rAF 被重复启动,存在两个循环在推进 elapsed;② `dt` 计算时没有判断 `running`,暂停时仍把时间差累加进 `elapsed`;③ 暂停期间 `lastMs` 没有更新,恢复时第一次 dt 特别大导致突跳;④ 全局速度读取位置错误,速度为 0 时仍在累加。
- **我逐项测试的结果**:
  ① 用 Console 检查 frameHandle 只在构造时赋值一次 → 排除;② 按 AI 思路定位到 `tick()` 的 `dt`:原本应写 `dt = (running && globalSpeed>0) ? min(raw,0.1) : 0`,我故意先去掉 running 判断制造该 Bug → 实测复现“已暂停但数值在变”(d1≠d2);③ 恢复正确写法后重载页面 → 暂停 1 秒内数值完全冻结(1.54×/1.54×),继续后恢复推进(1.54→1.85)→ 确认修复;④ dt 上限 0.1s 同时防后台标签恢复突跳。
- **真正原因、修改位置和复测结论**:
  真正原因:`js/app.js` 的 `tick()` 中 `dt` 未受 `running/globalSpeed` 约束,暂停只改了 UI 状态、没停住动画时间。
  修改位置:`tick()` 中 `const dt = (this.running && this.globalSpeed>0) ? Math.min(raw,0.1) : 0;`。
  复测结论:暂停冻结、继续推进、速度 2 倍明显变快,全部符合验收要求。

---

## 协作3:设计方案比较与实现核验(Task E,3分)

- **待解决的具体设计问题**:
  ① 多对象如何组织数据,才能做到“改菜单不影响已创建对象、各对象独立运动”;② PNG 截图如何保证不是空白/黑色。
- **关键提示词(原文)**:
  “Task D/E 里多个对象要各自独立运动,参数快照和全局速度怎么分工?截图用 toBlob 时怎么避免截出空白?”
- **两种方案及取舍依据**:
  - 数据组织:方案A“每帧从全局菜单读参数生成矩阵”(实现最简单,但改菜单会连带改变所有旧对象,违反参数快照规则);方案B“创建时把 direction/amplitude/scaleMax/axis/pivot/speed 存入对象自身,动画只基于 `elapsed` 状态计算”(正确性:旧对象参数固化、新对象互不影响;可维护性:对象自包含,新增模式只需扩展 `modelFor`;代价:`selectOptions()` 多一层快照逻辑)。采用方案B。
  - 截图:方案a“直接 `canvas.toBlob()`”(若绘制缓冲被交换/清除可能输出空白/黑色);方案b“截图前主动 `draw()` 重绘当前帧 + `preserveDrawingBuffer:true` 双保险,再 `toBlob` 下载”(时间成本一帧重绘可忽略,正确性高)。采用方案b。
- **我最终采用的实现**:
  `js/app.js`:`selectOptions()` 返回参数快照传给 `createObject()`;`savePNG()` 先 `this.draw()` 再 `toBlob`,用临时 `<a download>` 触发下载并回收 ObjectURL;`applyCanvas()` 调 `renderer.resize()` 同步更新 viewport 与正交投影后重绘保留对象。
- **测试与反思**:
  按验收情境在 `task-e.html` 实测:添加圆、两个方向不同的三角形、世界原点与自身中心两个正方形、Y 轴四面体共 6 个对象 → 暂停/继续/1.5 倍速正常;画布改 `960×540` 后圆仍为圆、中心点击仍得 `(0,0)`;点击“保存PNG截图”实际下载 `实验3_画布_20261019_102506.png`,校验为合法 PNG、尺寸 `960×540`、含全部图形与浅色背景(非空白);一键清屏后计数归零、再添加对象运行正常。反思:先想清“矩阵右乘先执行”与“状态快照”两个概念,能同时避免公转/自转写反和旧对象被菜单污染两类问题。

---

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

- 工具:豆包(Doubao);内容:WebGL2 初始化、`gl.drawArrays` 顶点数核对、鼠标坐标映射公式 `x=(2u-1)·aspect, y=1-2v`、`toBlob` 下载回调写法。处理说明:全部经过 `node --check` 语法校验、Node 数学自测与浏览器逐页实测(A~E 五个页面 Console 无阻断错误);未使用 CDN/外部框架。