AI 协作日志

学生 Web 实验作品平台

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

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

AI工具:ChatGPT(网页版对话)

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

**我要搞清楚的事**
Task B 要比较同一个正方形"绕世界原点转"和"绕自身中心转"的区别,我想弄明白 `T·R` 和 `R·T` 到底差在哪。

**我自己的预判(问 AI 之前先想过)**
我猜 `R·T(C)` 是让正方形绕画布中心画圈(公转),`T(C)·R` 是原地自转。但我拿不准"列向量下右边先执行"该怎么理解

**我问的原话**
> T·R 和 R·T 哪个先执行啊?

**AI怎么说**
- 列向量下连乘右边先执行:`R·T` 是先平移到 C、再绕世界原点转 → 整体公转;`T·R` 是先自转、再平移到 C → 原地自转。
- 平移只影响 `w=1` 的点,`w=0` 的方向向量不会因为平移而改变。

**我自己做的验证**
打开 task-b.html,先看页面下方「矩阵数值检验」那 5 项,再把「旋转中心」在 world / self 之间来回切,盯着同一个正方形看。

**实际看到的结果**
5 项数值测试全部显示 ✓,数值依次是 `(1.3,-0.2,0,1)`、`(2,0,0,1)`、`(0,1,0,1)`、`(0,0,-1,1)`、`(1,0,0,0)`,和指导书第 6 点那张表完全对得上(最后一项就是方向向量不受平移影响)。world 模式下正方形确实绕画布中心画圈,self 模式下原地转,两个轨迹一眼就能看出不同。

**我的结论**
AI 说的和我猜的方向一致,但我原本对"右边先执行"的理解是错的。这次是靠那 5 项数值 + 亲手切开关看轨迹才真正记住的,不是听 AI 说完就会了。

## 协作2:故障诊断与修复(Task B/C 页面打不开)

**错误现象**
打开 task-b.html 和 task-c.html 完全没反应——B 的数值测试区域是空的,C 也不动;但 task-a、task-d、task-e 三个页面都正常,刷新也没用。

**我先自己查了什么**
我先怀疑是代码里查的控件 id 和 HTML 对不上(因为 updateB 里写的是 `$('bTranslateFields').hidden`,一旦查不到元素、再去访问属性就会报错、整页卡死)。我把两个 HTML 的控件 id 和代码里的引用逐个比对了一遍,发现**全部对得上**,这个猜测排除了。接着我比较 B/C 和 A/D/E 的差别,注意到只有 B 和 C 会用到**旋转矩阵**,A/D/E 不用。

**我问的原话**
> webgl页面打不开,另外几个页面都正常,怎么快速定位是哪出错了

**AI给的排查思路**
1. DOM 控件 id 不匹配,在 null 上访问属性抛错;
2. 调用了库里不存在的方法;
3. Shader 编译失败或 WebGL 上下文创建失败。

**我逐项试的结果**
- 第1条:id 全部匹配,**排除**。
- 第2条:我去 `common/gl-matrix.js` 里搜了一下,发现它只是个**精简子集**,里面只有 `fromXRotation / fromYRotation / fromZRotation`,**并没有** `fromRotationX/Y/Z`。而我 `js/transforms.js` 里的 `R()` 用的正是后者——一调用就报 is not a function,初始化和动画循环全被中断。**就是它。**
- 第3条:A/D/E 能正常画出来,说明 Shader 和上下文没问题,**排除**。

**真正原因、改在哪、复测结果**
真正原因是旋转矩阵的函数名和这个精简库对不上。修改位置:`js/transforms.js` 的 `R()`,改成 `fromXRotation / fromYRotation / fromZRotation`。改完后:B 的 5 项数值测试全 ✓;C 的四种动画都正常(圆 1↔2 倍循环、三角形往复且不漂移、正方形绕画布中心公转、四面体绕自身 Y 轴自转,暂停 2 秒再继续也不突跳);D 里添加会旋转的正方形/四面体也不再卡死。

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

**要解决的问题**
Task E 要能一键把当前画面存成 PNG。我怕截出来是黑图或空白,也不太明白为什么只改 CSS 尺寸不算数。

**我问的原话**
> canvas.toBlob 截webgl的图出来是黑的,怎么解决

**两种做法和我的取舍**
- 做法A:创建上下文时开 `preserveDrawingBuffer`,直接 `toBlob`。省事,但得保证截图那一刻缓冲里确实有画面。
- 做法B:不开 preserve,截图前先重绘一帧再 `toBlob`。省一点,但时序没卡准就容易截到空缓冲。
- 我的取舍:框架本来就开了 `preserveDrawingBuffer`,我又在 savePNG 里先主动 `draw()` 一次再 `toBlob`,两个都占着,最稳。另外只改 CSS 宽高并不会改 Canvas 的**内部像素**和正交投影,圆会被拉扁,所以必须用 `renderer.resize()` 同时更新内部尺寸、`gl.viewport` 和投影。

**最后怎么实现的**
`js/app.js` 的 `savePNG()`:先 `this.draw()`,再 `toBlob(..., 'image/png')`,用临时 `<a download>` 存成 `实验3_画布_时间.png`,最后回收临时 URL。

**我实际跑的结果**
点「保存PNG截图」后确实下载出了文件。打开检查:尺寸等于画布内部像素、有设置的背景色和全部图形、不是黑图——三项都对,说明"截图前主动重绘 + preserveDrawingBuffer"这个双保险是真的有用。

## 其他用AI的地方
- Task A 要求指出"局部顶点 / GPU Buffer / 绘制"三部分在哪,AI 帮我定位到 `js/graphics.js` 的 bufferData 和 drawArrays,我按指导书要求在代码里加了注释明确标出这三处。
- Task D 鼠标坐标转世界坐标的换算(中心 (0,0)、Y 朝上、`x∈[-a,a]`),AI 帮我复核了公式,和指导书 3.3 节一致。