AI 协作日志

学生 Web 实验作品平台

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

# 实验五AI协作与核验记录(学生填写)

学号:202412211401013    姓名:陈妍煜    日期:2026-11-9

> 必须记录**自己的预测、原始问题、AI建议、自主判断与实际核验**。AI代码不能代替本人解释。可附完整对话链接/导出记录,避免只放聊天截图而无测试证据。


## 协作一:观察与投影概念核验(Task B / C,3 分)

1. **我的问题和事先预测(M/V/P 中谁变化?预期画面如何变化?)**

我准备做三组对照,并先在纸上写下预测再问 AI:

- **只改 V**(eye 从正面 `(0,0,8)` 换到侧面 `(8,0,0)`):画面应变成侧视,但 "世界位置" 应仍是 `(0.00,0.00,0.00)`,"Model 参数" 仍是 `T(0,0,0) Rx0° Ry0° S1.00`。理由是相机只改变 `V=P·V·M·N` 中的第二个矩阵,不碰模型世界坐标。
- **只改 P**(同一 M、同一 V,正交 ↔ 透视):如果我判断对,"两个等尺寸立方体" 在**正交**下应**完全等大**,在**透视**下应**近大远小**;并且切换时 "相机"" 世界位置 ""Model 参数" 三栏一个数都不能变。
- **只改 M**(键盘 `D` 按三次,`tx 0→0.45`):世界中心 X 应变 `0.45`,而**相机 eye/target 不变**。
- 我的核心预测结论:**"画面看起来变了" 不足以判断原因,必须同时看 "世界坐标 + Model 参数 + 相机参数" 三栏谁动了。**

2. **我实际输入给 AI 的提示词**

> 
> 在 WebGL2 右手坐标系、列向量和 P・V・M 的顺序下,我想比较移动物体与移动相机、正交与透视投影。请给我三组能区分原因的控制变量实验,指出应改变 M/V/P 中的哪项,说明可以打印哪些坐标数值进行核验,不要直接生成整套代码。

3. **AI 建议摘要(包括关键数学依据)**

AI 给的三组控制变量与可打印量:

- **M 组**:固定 `V`、`P`,只改 `tx/ty/tz/rx/ry/scale`。核验量:`CG5.point(M·N, stats.center)`(因为 `N` 已把包围盒中心归零,这一项恒等于 `(tx,ty,tz)`),以及 `stat-camera` 字符串必须不变。
- **V 组**:固定 `M`、`P`,只改 `eye/target`。核验量:同一条 "世界中心" 表达式的结果必须**逐字不变**;同时打印 `Array.from(V)`,正面时 `V` 是纯平移(索引 14 = −8),侧面时出现旋转项。
- **P 组**:固定 `M`、`V`,只换 `P`。核验量:打印两种 `P` 的关键元素 —— 正交 `m[0]=2/(h·aspect)`、`m[5]=2/h`、`m[10]=−2/(far−near)`;透视 `m[0]=cot(fov/2)/aspect`、`m[5]=cot(fov/2)`、`m[11]=−1`、`m[14]=−2·far·near/(far−near)`。
- 数学依据:正交矩阵第四行是 `(0,0,0,1)`,即 `w_clip ≡ 1`,没有除以深度的过程;透视矩阵把 `w_clip = −z_eye`,光栅化前的透视除法 `x_ndc = x_clip/w_clip` 使屏幕尺寸与深度成反比,这就是近大远小的唯一来源。
- AI 还建议:可以用 `CG5.point(P, 世界点)` 直接得到 "已做完透视除法" 的 NDC 坐标,用同一个世界点投两次(正交 / 透视)比较 NDC 宽度比值。

4. **我的判断和采纳 / 拒绝理由**

- **采纳**:用 "世界中心字符串是否逐字相同" 作为 M/V 分离判据;用 `P` 对角线元素 + `aspect` 作为 P 的书面证据。这两条都能给出可比对的数字,比截图可靠。
- **采纳但改造**:AI 建议 " 写一个 helper 临时把 `state.mode` 设成 ortho/persp 再取矩阵 "。我**拒绝**这个写法 —— 改 `state` 会污染后续帧、破坏控制变量,甚至在双画布场景里根本不可行(一帧只能有一个 `mode`)。我改成给 `ex.projection` 传一个**临时参数对象** `{mode:"ortho",...}`,`state` 不动。
- **拒绝**:AI 一开始把 "转物体与转相机看起来相似" 直接归因于 "矩阵顺序不同"。我认为这个解释不成立 —— 两种操作在单物体场景下得到的**相对位姿**本来就相同,顺序不是原因。

5. **我的测试参数、测试操作与结果(附截图 / 数值)**

表格

| 测试 | 改变项 | 参数 | 实测(Console / 状态栏) | 判定 |
| --- | --- | --- | --- | --- |
| ① V 组 | 只改 V | 正面 `(0,0,8)` → 侧面 `(8,0,0)`,M、P 不动 | `世界位置` 两次均为 `(0.00, 0.00, 0.00)`;`Model参数` 两次均为 `T(0.00,0.00,0.00);Rx 0°,Ry 0°;S 1.00`;仅 "相机" 变化 | M 未动,V 生效 |
| ② V 组的矩阵证据 | 只改 V | 同上 | 正面 `V = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,-8,1]`(纯平移,索引 14=−8);顶部为绕 X 旋转项 | V 由 eye/target/up 决定 |
| ③ P 组 | 只改 P | 同一 `M`、同一 `V`,正交 `h=7.46` vs 透视 `fov=50°`,`near/far=0.1/100` | 正交两立方体 NDC 宽 **0.1306 / 0.1306**(远 / 近 = 1.000);透视 **0.1307 / 0.0950**(远 / 近 ≈ 0.727) | 差异只来自 `w_clip` |
| ④ M 组 | 只改 M | 键盘 `D` ×3 | `tx=0.45`,世界中心 `(0.45, 0.00, 0.00)`;相机 `eye (0.00,1.80,8.50)` 不变 | M 与 V 解耦 |
| ⑤ 往返一致 | 只改 V | 正面→侧面→正面各存 PNG | 首尾两张 PNG 像素一致,`V` 数值相同 | 无状态漂移 |

附截图:`B_front.png`、`B_side.png`、`B_top.png`(顶部无黑屏)、`C_ortho.png`、`C_persp.png`(同 M/V 仅切 P)、`D_after_key.png`。

6. **AI 是否正确?我最终修正了什么认识?**

- 关于 `w_clip=1` 与 `w_clip=−z_eye` 的数学解释**正确**,可被 Console 数值直接验证(③ 的两个 NDC 宽比值 0.727 ≈ 8/11 的倒数关系)。
- 关于 "转物体≈转相机" 的归因**不正确**,我修正为:单物体时两者只是 "相对位姿相同",多物体时物体间的**世界相对位置**由 M 决定、相机只负责成像,因此不等价。
- 我最终确立的判据:**先看世界坐标与 Model 参数有没有动(区分 M/V),再看投影矩阵元素与 aspect(区分 P)**,最后才谈画面像不像。

## 协作二:程序故障诊断(Task C / D,4 分)

1. **真实错误现象和我起初怀疑的原因**

现象:Task C 切到正交投影后,茶壶和两个立方体被**横向拉宽**、球体变椭圆,透视下正常;把浏览器窗口拉成接近方形时,椭圆又变回圆。

我起初怀疑两件事:①透视 / 正交矩阵相乘顺序写错(`P·V·M·N` 写成了 `V·P·M·N`);②`near/far` 取值不当把模型裁掉了。

2. **向 AI 提出的诊断问题**

> 
> 我的 OBJ 能显示,但切换透视投影后形状被拉伸 / 裁剪或者鼠标拖动方向异常。请从宽高比、裁剪面、矩阵顺序和观察基向量中提出至少三种假设,分别给一项最小测试,先帮助排查,不要直接重写完整程序。

3. **AI 建议的至少两个可区分原因及测试**

- **假设 A(宽高比)**:`P` 里用的 aspect 与 canvas 实际 `width/height` 不一致,或正交左右边界没乘 aspect。最小测试:把窗口拉成 1:1 观察椭圆是否恢复为圆;同时打印 `canvas.width/canvas.height` 与状态栏 aspect 是否一致。
- **假设 B(裁剪面)**:`near<=0`、`far<=near` 或相机距离超出 `[near,far]`。最小测试:把 `far` 改到小于相机距离、`near` 改到大于相机距离,观察是 "被切掉" 还是 "形状变形"(裁剪只会缺一块,不会把圆压扁)。
- **假设 C(矩阵顺序)**:`P·V` 与 `V·P` 混用。最小测试:临时交换顺序后看模型是否整体飞出视野 / 消失;再用 `CG5.point` 打印同一点在两种顺序下的 NDC。
- **假设 D(观察基向量)**:`up` 与视线平行或 `right = up × forward` 顺序反了。最小测试:切顶部视角是否黑屏 / NaN;侧视 Shift 右拖看 `tz` 增大还是减小。

4. **我实际逐项测试了什么?各自结果如何?**

表格

| 假设 | 最小测试 | 结果 | 结论 |
| --- | --- | --- | --- |
| A 宽高比 | 窗口拉成近 1:1;打印 `canvas 1000×650` → aspect **1.60**,与状态栏一致 | 拉成方形后圆恢复为正圆;但 aspect 数值本身是对的 | **不是 aspect 数值**,而是正交矩阵**没用** aspect |
| B 裁剪面 | `far=10`(相机距离 8.68)、`near=9` | 表现为 "整块物体消失 / 前部被切",**形状不变形** | 排除 |
| C 矩阵顺序 | 临时把 `scene.projection` 改成 `V·P` | 模型整体飞出视野、画面基本空白,与 "拉伸" 截然不同 | 排除 |
| D 基向量 | 顶部视角、侧视 Shift 右拖 | 顶部正常不黑屏;侧视右拖 `tz` 减小 | 排除(且顺带验证了 D 的方向正确) |

进一步定位:直接打印正交矩阵对角元素,发现 `m[0]=2/h=0.2667`、`m[5]=2/h=0.2667`,**两轴相同**,说明投影盒是 1:1;而视口是 1.6:1,NDC 被视口横向拉宽了 1.6 倍。

5. **最终根因、修复处及修复后结果**

- **根因**:正交分支写成了
`mat4.ortho(out,-h/2,h/2,-h/2,h/2,near,far)`,
**左右边界也用了 h,没有乘 aspect**,投影盒宽高比恒为 1:1。
- **修复处**(`js/task-c.js`):
```
const w=h*aspect;
return CG5.mat4.ortho(CG5.mat4.create(),-w/2,w/2,-h/2,h/2,near,far);
```
- **修复后**:`m[0]=2/(h·aspect)=0.1667`、`m[5]=2/h=0.2667`,是 1.6:1 的盒子;任何窗口尺寸下球都是正圆、两个立方体严格等大(NDC 宽 `0.1306/0.1306`);`near/far` 的错误提示仍然正常(红字 "near 必须大于 0。")。
- 同一轮里我还确认了 D 的次级现象:**侧视 Shift 右拖时 `tz` 必须减小**,因为侧视时 `right = forward × up = (0,0,-1)`;若写成 `up × forward` 就会变成 `tz` 增大(方向镜像)。

## 协作三:综合工作台方案比较(Task E,3 分)

1. **我准备完成的观察任务**

做一个 "茶壶 / 兔子绕指定参考点观察" 的工作台:模型自动归一化、多视角、正交 / 透视可切、鼠标键盘可 T/R/S,另外有一个**绕世界参考点 P 运行的标记**,能通过输入改变 P 并验证 `T(P)·R·T(−P)` 的坐标效果。

2. **向 AI 询问的两种设计方案**

提问用指导书原提示词:

> 
> 我已完成 OBJ 导入、观察视角、正交 / 透视以及鼠标键盘变换。请提供两个能在 40 分钟内复用已有 WebGL2 模块的观察台拓展设计,对比功能、矩阵链、交互参数和验证难度。不引入 Three.js、光照、纹理或复杂模型编辑器。

AI 给的两个方案:

- **方案一(绕点轨道)**:`extra` 返回 "参考点标记 + 绕 P 运动的标记",矩阵链 `M_orbit = T(P)·Ry(θ)·T(−P)·T(q)·S`;交互参数为 `orbit` 与 `P=(px,py,pz)`。
- **方案二(双画布投影对照)**:新增一页,两个 canvas、两个 `CG.Scene`,共用一份 `M` 与 `V`,左侧 `P₁=ortho`、右侧 `P₂=perspective`,交互参数为 `fov`(右)与 `orthoH`(左)。

3. **两种方案的功能、矩阵链、测试难度对比**

表格

| 维度 | 方案一 绕点轨道 | 方案二 双画布对照 |
| --- | --- | --- |
| 功能增量 | 新增 "指定点旋转 + 参考点可视化",可输入 P | 新增 "同 M/V、仅 P 不同" 的并排对照,拖动同步 |
| 矩阵链 | `T(P)Ry T(−P) T(q) S`(在 M 之后追加一层复合变换) | `P·V·M·N` 中 M/V 只算一次,P 算两次(`ortho`/`perspective`) |
| 交互参数 | `orbit`(度)、`px/py/pz`(世界坐标) | `fov`、`orthoH`、`near/far`、`eye/target` |
| 验证难度 | **低**:单点坐标可打印(半径恒定 1.36,角度 0/90/180 有闭式解) | **中**:要保证两块画布尺寸 / 宽高比一致,还要组合截图;需要两个 WebGL2 上下文 |
| 复用成本 | 只改 `ex.extra`,加 3 个 `data-field` | 需要新页面 + 新 JS,不能沿用 `app.js` 的单画布生命周期 |
| 40 分钟内可行性 | 高(约 15 分钟可跑通) | 中(约 25–30 分钟,调试双上下文) |

4. **最终采纳的方案与理由**

**最终由我决定:方案一作为 E 的主体,方案二单独做成 `challenge.html` 作为加分项。** 理由是我要保证必做项稳、加分项独立:E 的 15 分里 "复合机制 + 自主设计" 必须有可数值验证的证据,绕点轨道的坐标是闭式的、最容易证;而双画布对照需要两个上下文,风险独立,放在 Challenge 里即使出问题也不影响 E 的验收链。AI 倾向让我 "直接把双画布并进 E",我没有采纳,因为那会改动 `app.js` 的单画布生命周期,违反 "不随意改框架" 的约束。

5. **自己实现或修改的功能差异**

- `js/task-e.js`:`ex.extra` 返回两个对象(参考点、绕点标记),矩阵为 `T(P)·Ry(θ)·T(−P)·T(q)·S`,其中 `q = P + (1.1, −0.8, 0)`;
- `js/ui.js`:在 level-5 面板中**新增** `px/py/pz` 三个 `data-field` 输入(沿用框架的 `fields` 自动绑定,未改任何渲染逻辑)—— 这就是 "实质性功能修改":把写死的参考点变成可交互参数;
- 额外新增 `challenge.html` 与 `js/challenge.js`,实现正交 / 透视双画布同步对照(Challenge 1),未改动 A–E 的任何文件。

6. **预测与实际结果对照,仍存在的局限**

预测与实测:

表格

| 预测 | 实测(Console) |
| --- | --- |
| `orbit=0` 时标记中心在 `q=(1.10, 0.40, 0)` | `(1.10, 0.40, 0.00)` ✓ |
| `orbit=90` 时在 `(0, 0.40, −1.10)` | 一致 ✓ |
| `orbit=180` 时在 `(−1.10, 0.40, 0)` | 一致 ✓ |
| 三档到 P 的距离恒为 1.36 | 三档均为 **1.36** ✓ |
| 改 `px=0.8` 后圆心平移、半径不变 | 圆心平移,半径仍 1.36 ✓ |

仍存在的局限:

- 标记用框架的立方体,没有光照 / 材质,"绕点" 更多靠位置判断而非视觉纵深;
- 正交下轨迹等宽,缺少透视的 "前大后小",反而看不出深度信息;
- 状态栏只显示 M 的 T/R/S,没有显示 V 与 P 的矩阵数值,削弱了 "数值可核验" 的直观性;
- 双画布页在窄窗口下会堆叠成上下两栏,此时 "并排对照" 退化为 "上下对照",需要在报告里注明。

## 全局诚信声明

- 我提交的代码均已本人运行并核验;无法解释的 AI 输出未直接作为完成结果。
- 我明确标注了使用 AI 辅助的功能和本人自主完成的关键判断。