AI 协作日志
学生 Web 实验作品平台
学号:202412211402024 · 来源:ai-log.md
# 实验三 AI协作记录(请学生在实际完成实验后填写) > 教师参考代码包不包含虚构的AI协作过程。学生提交时需填写真实工具、提示词、独立测试与结论。 # 实验三 AI协作与核验记录 AI工具:豆包 ## 协作 1:矩阵与变换次序 - 我的目标和预先预测: 正方形初始中心设置为 (0.5, 0.25)。 预测:`R * T`(world 模式):先平移到目标位置,再执行旋转,图形会绕世界原点做公转运动; 预测:`T * R`(self 模式):先对局部模型旋转,再平移到目标位置,图形在自身中心点原地自转,整体位置不会发生环绕偏移。 - 关键提示词(原文): WebGL 使用列向量,矩阵乘法 M1*M2 代表 M2 先作用于顶点。请解释 R・T 与 T・R 两种矩阵组合,T 代表把物体平移到 (0.5,0.25),Rz 为 45 度旋转;分别说明 world 公转、self 自转的矩阵写法以及运行出来的视觉现象。 - AI 建议摘要: 1. 列向量规则:矩阵乘法**右侧矩阵优先执行变换**。 2. `multiply(R, T)`即 R・T:先执行平移 T,将模型移动到指定坐标,之后执行旋转 R。物体绕世界坐标原点公转,图形位置会绕画布原点转圈。 3. `multiply(T, R)`即 T・R:先在局部坐标系完成旋转 R,再平移 T 到画布指定位置。物体只在自己的中心原地自转,物体整体位置保持不变。 4. 实验页面可以切换 pivot 参数,对比两种模式观察正方形轨迹,页面内置的矩阵单元测试也可以辅助验证矩阵计算正确性。 - 我的计算或测试方法: 打开 task‑b 页面,保持参数:shape = 正方形,mode = 旋转,centerX=0.50,centerY=0.25,angle=45;分别切换 pivot 为`world`和`self`,观察正方形运动轨迹;同时查看页面底部矩阵测试模块打勾情况。 - 实际结果与证据: 1. pivot=world:正方形绕画布世界原点转圈,发生公转,符合预期。 2. pivot=self:正方形固定在 (0.5,0.25) 原地旋转,位置不变。 3. 页面 5 项矩阵单元测试全部✓通过,矩阵计算结果正确。 - 采纳、拒绝或修正的结论: 采纳 AI 给出的解释。充分理解**列向量矩阵乘法:右边矩阵先变换**,变换顺序直接决定物体运动行为,不能随意交换矩阵相乘顺序。 ## 协作 2:故障诊断与修复 - 错误现象、触发步骤: Task‑C 动画页面,点击暂停按钮等待 2 秒,再点击继续动画,画面里面所有物体瞬间大幅度跳变,不是接着之前状态平滑继续运动。 - 我先检查了什么: 1. 检查 requestAnimationFrame 调用逻辑,确认没有重复创建 rAF 循环。 2. 怀疑是 lastMs 时间戳没有处理暂停状态。 - 关键提示词(原文): requestAnimationFrame 做 WebGL 动画,暂停一段时间恢复后物体时间瞬间跳变,一般有哪些原因,请给出逐项排查思路。 - AI 列出的候选原因: 1. 暂停状态下仍然在计算帧时间差 dt,对象 elapsed 一直在后台累加时间; 2. dt 没有做最大值限制,浏览器切后台回来会产生巨大时间差; 3. lastMs 变量没有在暂停的时候冻结; 4. 多处重复调用 requestAnimationFrame,产生多个动画循环。 - 我逐项测试的结果: 1. 查看 tick 函数,原始代码无论是否`this.running`,都会计算 dt 并且累加 obj.elapsed。暂停时虽然画面不动,但是时间还在跑,恢复瞬间直接跳转到很久之后的动画状态,这就是 bug 根源。 2. 增加判断:只有`this.running === true`的时候,才执行每个对象 elapsed 时间累加;同时增加`if(dt>0.15) dt=0.15`限制最大帧间隔。 - 真正原因、修改位置和复测结论: 修改位置:`js/app.js`的`tick()`函数。 根因:暂停状态依然累计动画时间。修复后复测:暂停 2 秒,再点击继续,物体从暂停位置平滑继续运动,不再发生瞬间跳跃,现象符合预期。 ## 协作 3:方案比较与实现核验 - 待解决的具体设计问题: WebGL Canvas 调用 toBlob 导出 PNG 截图,有两种实现思路;本项目已经开启 preserveDrawingBuffer:true,对比两种方案优缺点,选择合适的实现。 - 关键提示词(原文): WebGL canvas 使用 toBlob 经常得到空白黑色截图,本项目开启 preserveDrawingBuffer,请对比两种实现方案:方案一直接调用 toBlob;方案二调用 draw 刷新画面之后再 toBlob;分析取舍。 - 两种方案及取舍依据: 方案 1:直接执行 canvas.toBlob (),不调用 draw。 缺点:浏览器有可能丢弃 WebGL 后台帧缓冲,拿到空白黑色截图;虽然开启 preserveDrawingBuffer,依然存在风险。优点代码行数少。 方案 2:先手动调用`this.draw()`强制重绘一帧完整画面,再执行 toBlob。 缺点:会多执行一次绘制,性能开销微小,对于本实验完全可以接受; 优点:保证帧缓冲内存存放最新一帧图形画面,截图稳定可靠,不会出现黑色空白。 - 我最终采用的实现: 在`savePNG()`函数最开头执行`this.draw()`,刷新画布;使用 toBlob 获取 blob 对象;创建临时 a 标签触发下载;下载完成调用`URL.revokeObjectURL(url)`释放浏览器内存,防止内存泄漏。 - 测试与反思: 在 task‑e 页面修改画布大小、修改背景颜色,添加若干运动对象,点击保存 PNG。导出 PNG 图片尺寸和 Canvas 像素尺寸完全一致,图形、背景色全部正确,没有出现黑屏截图。 反思:WebGL 是双缓冲机制,做截图导出操作,需要保证缓冲内是最新渲染画面,不能直接拿缓冲,优先主动 draw 刷新再导出。