AI 协作日志
学生 Web 实验作品平台
学号:202412211401026 · 来源:ai-log.md
# 实验三 AI协作记录
AI工具:Trae IDE 内置 AI 助手(Kimi-K3 模型)
## AI协作1:矩阵和变换次序
- 我自己的预测:对中心 C=(0.50,0.25,0)、θ=45° 的正方形,先用纸笔手算两种次序。预测 `M=Rz(45°)·T(C)`(列向量右侧先执行,先平移到 C 再绕世界原点转 45°)会把中心移到 (0.5·cos45°−0.25·sin45°, 0.5·sin45°+0.25·cos45°) ≈ (0.177, 0.530),且正方形朝向随公转改变;而 `M=T(C)·Rz(45°)` 的中心仍是 (0.500, 0.250),只在原地自转 45°。因此两者通常不相等:矩阵乘法不可交换,平移分量会被左侧的旋转再次变换。
- AI工具与原始提示词:`WebGL中列向量矩阵 M=Rz(θ)*T(C) 与 M=T(C)*Rz(θ) 对中心在(0.5,0.25)的正方形分别是什么效果?为什么右侧矩阵先执行?如何用矩阵最后一列直接读出两种模式差别?`
- AI的建议:确认列向量约定下右侧矩阵先作用于顶点;R·T 表现为绕世界原点公转、T·R 表现为绕自身中心自转;建议不要只看画面,直接读取 4×4 矩阵的平移列(第 12/13 个元素)做数值对照;并提醒方向向量 w=0 时平移列被乘以 0,所以方向不受平移影响。
- 本人计算、运行与证据:在 task-b.html 设中心 (0.50, 0.25)、角度 45°、旋转中心“世界原点”,页面“当前Model矩阵”平移列实测为 (0.177, 0.530);切换为“对象中心”后平移列变为 (0.500, 0.250),旋转部分保留在左上 3×3。两组数值与手算完全一致;画面上世界原点模式的正方形明显偏转到中上方,对象中心模式在原中心原地转。页面“矩阵数值检验”5 项(含 w=0 方向向量平移不变)全部显示 ✓。
- 采纳或修正结论:采纳 AI 建议(与我事先预测一致)。额外收获:用“平移列是否随时间变化”可以快速区分公转与自转,该方法后来沿用到 Task C/D 的验收。
## AI协作2:实际故障排查
- 错误现象与重现步骤:打开起始学生版 task-a.html,画布中只有圆形,三角形、正方形、四面体均不显示;task-c.html 中四个对象全部静止不动。
- 我先检查了什么:浏览器 Console 无报错;Shader 编译成功(否则 initShaders 会抛错);`js/geometry.js` 中四种 mesh 顶点数据存在;`Graphics.debugStats()` 显示四种 Buffer 字节数正常。因此排除路径、Shader 与 Buffer,把范围缩小到绘制调用与动画时间。
- AI工具与原始提示词:`WebGL2 中 bufferData 已上传四种网格但只有第一种被画出,gl.drawArrays 的 count 参数传 0 会怎样?另外 requestAnimationFrame 动画里对象位置逐渐漂移的常见原因有哪些?`
- AI建议的候选原因与测试:(1) drawArrays 的 count 为 0 时不产生任何图元、也不报错——检查 draw 循环里 count 的来源;(2) 动画不动的候选:dt 恒为 0、暂停标志未生效、rAF 重复启动、elapsed 未按对象更新;(3) 漂移候选:每帧对“当前中心”累加位移造成浮点累积、暂停期间 dt 未清零、速度切换时积分不连续。建议用“初始中心 + 周期函数”替代累加,并给 dt 加上限。
- 实测结果、修复与复测:定位到 `js/graphics.js` 中占位代码 `drawCount = item.type==='circle' ? mesh.vertexCount : 0`,非圆形状 count=0 被静默跳过——改为统一 `mesh.vertexCount` 后四种形状全部显示。动画不动是 `tick()` 中 `dt=0` 占位所致,实现 dt=(ms差)/1000 并限制 ≤0.1s、仅运行且速度>0 时逐对象累加 elapsed 后恢复。按 AI 建议,平移一律由 `obj.center + amplitude·sin(2π·t/period)` 即时计算,center 永不修改;复测:运行 5 个周期三角形位移仍在 ±0.30 内无漂移,暂停 2 秒继续无突跳,速度调到 2 倍后明显变快。
## AI协作3:设计方案比较
- 我考虑的两种实现:Task E 的 PNG 截图。方案一:`canvas.toDataURL('image/png')` 同步取 base64 字符串赋给 `<a href>` 下载;方案二:先主动 `this.draw()` 重绘,再 `canvas.toBlob(callback,'image/png')` 异步取 Blob,用 `URL.createObjectURL` + 临时 `<a download>` 下载后释放 URL。两种都依赖绘制缓冲中有当前帧(本项目 Graphics 已设 `preserveDrawingBuffer:true`)。
- AI工具与原始提示词:`WebGL canvas 截图用 toDataURL 还是 toBlob?preserveDrawingBuffer:true 起什么作用?没有它时为什么可能截到空白图?`
- 对比、取舍与原因:toDataURL 同步生成整图 base64,大画布下阻塞主线程且内存占用高(字符串约为二进制 1.37 倍),但用法简单;toBlob 异步回调、内存友好、可直接生成对象 URL,代价是需在回调里处理空 Blob 与资源释放。AI 还指出:若无 preserveDrawingBuffer,浏览器在合成后可能清空绘制缓冲,截图需在同一个事件回调里先重绘再取图,否则得到空白/黑图。考虑到正确性优先,最终采用“先 this.draw() 重绘 + toBlob 异步导出 + preserveDrawingBuffer 双保险”的方案二。
- 实际实现及核验:实现于 `js/app.js` 的 `savePNG()`:重绘→toBlob→检查 Blob 非空→时间戳文件名 `实验3_画布_YYYYMMDD_HHMMSS.png`→下载→1 秒后 revokeObjectURL。核验:分别在 800×600 与改设 960×540 后保存 PNG,文件可正常打开,尺寸与 Canvas 内部像素一致,包含所设背景色与全部 WebGL 图形、非空白;清空画布后再截图也能正确反映空场景。反思:方案二代码略长,但避免了同步阻塞和 base64 开销,且“截图前主动重绘”这一习惯在去掉 preserveDrawingBuffer 后依然安全。