AI 协作日志
学生 Web 实验作品平台
学号:202312211503020 · 来源:ai-log.md
# 实验三 AI协作记录(请学生在实际完成实验后填写)
> 教师参考代码包不包含虚构的AI协作过程。学生提交时需填写真实工具、提示词、独立测试与结论。
## AI协作1:矩阵和变换次序
- 我自己的预测:
对初始中心 C=(0.50,0.25,0) 的正方形,R=Rz(30°)。我预测 T(C)·R 时正方形中心仍在 (0.50,0.25) 附近、只改变自身姿态(自转);R·T(C) 时中心会被旋转到 R·C,约为 (0.308,0.467),即绕世界原点公转。
- AI工具与原始提示词:
工具:ChatGPT
提示词原文:“在列向量约定下,glMatrix 的 multiply(a,b) 表示 a·b。请判断 T(C)·R 与 R·T(C) 哪个表示绕对象自身中心旋转、哪个表示绕世界原点旋转,并给出 C=(0.5,0.25)、R=Rz(30°) 时两者中心位置的大致数值。”
- AI的建议:
AI 指出列向量右侧先作用:T(C)·R 先旋转再平移到 C,中心不动(自转);R·T(C) 先平移到 C 再整体绕世界原点旋转,中心变为 R·C(公转),并给出 R·C≈(0.308,0.467),与我的预测一致。
- 本人计算、运行与证据:
Rz(30°)·(0.5,0.25):
x'=0.5cos30°−0.25sin30°=0.433−0.125=0.308;
y'=0.5sin30°+0.25cos30°=0.250+0.217=0.467。
在 task-b.html 选正方形、旋转、pivot=world,观察到正方形绕画布中心画圆;切 pivot=self,正方形中心不动只转姿态。
Console 执行 CG3TEST.matrixTests(),translate/scale/rotateZ/rotateY/vector 五项均与目标一致
- 采纳或修正结论:
采纳 AI 关于次序的解释,并用 R·C 手算值与页面现象双重核验;确认 bItem() 中 world 分支写 multiply(R,T(C))、self 分支写 multiply(T(C),R),与预测和运行一致。
## AI协作2:实际故障排查
- 错误现象与重现步骤:
打开 task-a.html,选择“四种形体(同时)”或切换三角形/正方形/四面体,画布始终只显示一个圆,其他形状不出现,Console 无报错。
- 我先检查了什么:
(1) Console 无报错,WebGL2 上下文、Shader 初始化成功;
(2) 菜单 option 的 value 为 circle/triangle/square/tetra,与 geometry.js 键名一致;
(3) geometry.js 四种形状 vertices 均非空,四面体为 4 面×3 顶点且为三维坐标。
- AI工具与原始提示词:
工具:ChatGPT
提示词原文:“WebGL2 页面无报错但只显示圆,其他形状不显示。geometry.js 已提供四种形状顶点。请列出可能原因和逐项排查步骤,重点检查绘制调用和形状数据上传。”
- AI建议的候选原因与测试:
候选原因:(a) 绘制分支写死只画圆;(b) 其他形状 Buffer 未上传或属性未绑定;
(c) drawArrays 的 count/mode 只对圆正确;(d) 对象数组里只有圆。
逐项测试:
查 app.js setupA(),发现 TODO A-02 占位实现只 create('circle',0,0),确认原因 (d);
查 graphics.js draw(),发现 `const drawCount = item.type==='circle' ? mesh.vertexCount : 0;`,非圆 count=0 被跳过,确认原因 (c)。
- 实测结果、修复与复测:
修复:app.js 的 A-02 按 choice 创建对象(all 用 positions 四角摆放,单个放画布中心);graphics.js 改为 `gl.drawArrays(gl.TRIANGLES, 0, mesh.vertexCount)`。
复测:切换菜单可分别看到圆/三角形/正方形/四面体;all 时四形状分列四角不重叠;四面体为立体、四面颜色可区分,转动时无穿插(深度测试生效)。
## AI协作3:设计方案比较
- 我考虑的两种实现:
方案一:每个对象维护“当前坐标/角度”,每帧累加 dt×speed。
方案二:对象只保存初始中心 center 与 elapsed,每帧用 center+f(elapsed,period,amplitude) 现算位置/角度/缩放。
- AI工具与原始提示词:
工具:Claude
提示词原文:“动画位置应每帧累加位移,还是保存 elapsed 从初始中心用时间函数现算?请比较两种方案在浮点漂移、暂停恢复、变速和可维护性上的取舍。”
- 对比、取舍与原因:
方案一实现简单,但长时间累加有浮点漂移,暂停/变速时相位难保持一致,恢复易突跳;方案二每帧从基准绝对计算,无累积误差,暂停不累加 elapsed 即可不突跳,变速只改时间缩放,且 Model 矩阵每帧重算、顶点 Buffer 一次上传复用,符合实验 Buffer 复用要求。
取舍:采用方案二,代价是需写 period/相位函数,但正确性与可维护性更好。
- 实际实现及核验:
transforms.js 实现 triangle01 与 modelFor:平移用 sin(2πt/period)、缩放用1+(scaleMax−1)·triangle01(t/period)、旋转用 deg2rad(angularSpeed·elapsed);tick() 中仅 running 且 speed>0 时累加 elapsed,并将 dt 限幅 0.1s。
核验:运行数周期圆仍在 1~2 倍、三角形两侧往返不漂移、正方形绕中心公转、四面体自转;暂停 2 秒画面不动、继续不突跳;全局速度 1→2 倍明显变快。
**思考题A:** 若只改变圆的显示位置,是否必须重新上传它的全部局部顶点?为什么?
不需要。圆的局部顶点只描述以局部原点为中心的形状本身,不包含它在画布上的位置,位置由 Model 矩阵(平移 T)在 Vertex Shader 中现算,因此只改显示位置时只需重新计算 uModel 并用 gl.uniformMatrix4fv 更新 Uniform 后重绘即可,GPU Buffer 中的局部顶点一次上传(STATIC_DRAW)后长期复用,重新上传既浪费 CPU→GPU 带宽、拖慢多对象场景,也违背本实验"几何只上传一次、变换靠 Model 矩阵"和 Buffer 复用的要求。
**思考题B:** 为什么`T(C)·R`与`R·T(C)`通常不相等?方向向量`w=0`为什么不会随着平移矩阵改变?
矩阵乘法一般不满足交换律,且按列向量"右侧先作用"的规则,R·T(C) 是先把物体平移到中心 C 再整体绕世界原点旋转,表现为沿圆周公转;而 T(C)·R 是先让物体绕原点自转再平移到 C,中心固定只改变姿态,除非 C=0 或 R 为单位阵,两者结果不同。方向向量在齐次坐标中写作 (x,y,z,0),平移矩阵第四列为 (tx,ty,tz,1),相乘时该列被 w=0 乘掉,只剩左上 3×3 的单位阵作用,所以向量保持不变——几何上向量只表示方向和长度、与位置无关,平移不改变朝向和大小。
**思考题C:** 为什么建议从对象的初始中心和时间参数计算位置,而不是持续对“当前坐标”累加位移?为什么动画可以持续更新Uniform而不重新上传所有顶点?
从初始中心和时间参数现算位置,是因为逐帧累加位移会累积浮点误差,导致长时间运行后漂移,且变速、暂停时相位难以保持一致;用绝对时间函数每帧从基准重算,无累积误差、恢复不突跳。动画只更新 Uniform 不重传顶点,是因为顶点描述形状本身、始终不变,每帧变的只是 Model 矩阵,几何 Buffer 一次上传即可长期复用,节省带宽并符合 Buffer 复用要求。
**思考题D:** 为什么对象需要同时保存“初始中心”和“当前动画状态”?为什么不能只保存GPU里的顶点数组?
对象需同时保存初始中心和动画状态:初始中心是变换基准,平移的位移、旋转的世界/自身中心、缩放的中心都依赖它;动画状态决定此刻的位置/角度/缩放,两者结合才能每帧重算 Model 矩阵。不能只存 GPU 顶点数组,因为顶点只描述不变的形状,既不含初始中心和变换参数,也无法表达随时间变化的动画状态,更无法区分各对象的独立运动;位置、朝向、大小都靠这些状态每帧算出矩阵。
**思考题E:** 为什么只用CSS改变Canvas显示宽高还不够?截图时为什么需要确认WebGL绘制缓冲中确实有当前画面?
只用 CSS 改宽高只是改变元素的显示尺寸,Canvas 内部的 width/height不变,gl.viewport 和正交投影也不会自动更新,于是绘图被拉伸、圆变椭圆,鼠标坐标映射也会偏移——必须同时改 canvas 内部尺寸、gl.viewport 和投影矩阵。截图前要确认绘制缓冲里确有当前画面,是因为 WebGL 默认绘制后缓冲可能被清空或交换,直接 toBlob 可能得到空白/黑图,需先主动重绘或设置 preserveDrawingBuffer:true再取图,才能保证导出的是正确画面。