AI 协作日志

学生 Web 实验作品平台

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

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

学号:______ 姓名:______ 日期:2026-11-09

> 本记录按“先预测→再向AI提问→人工选择测试→实际运行核验”的顺序整理;所有数值均由本人运行页面后用状态栏和矩阵打印得到。AI参与了思路讨论和代码草稿,但采纳与否由本人判断。

## 一、任务完成与自测摘要

| 任务 | 完成内容 | 关键核验 |
|---|---|---|
| A | `ex.normalize` 用包围盒中心 `c` 与最长边 `L` 构造 `N=S(2/L)·T(-c)` | 茶壶 858 顶点/1512 面,最长边 3.560,缩放 0.562;世界中心 (0.00,0.00,0.00) |
| B | 四个 eye 预设、`lookAt(eye,target,up)`、顶部视图换用 `up=(0,0,-1)`、eye=target 报错 | 顶部 View 与 `CG5Camera.safeView` 逐元素一致;世界中心不随相机改变 |
| C | 正交用 `orthoH·aspect` 构造,透视用 `fov·RAD`;校验 near/far/FOV | 正交 m00=0.2273、m55=0.3636;透视 m55=2.1445(FOV 50°);非法参数均抛出可读错误 |
| D | 左拖改 rx/ry;Shift 拖动按相机基换算世界位移;滚轮 dolly;键盘 T/R/S 与缩放 | 拖 (40,20) 像素得 rx=9°、ry=18°;按 D 后 tx=0.15;滚轮后距离 8.688→10.196,scale 仍为 1 |
| E | 绕点旋转标记 + 自拟“父子继承”卫星 + 轨道圆参考点 | 轨道角 0°→90°:橙色标记由 (1.55,1.25,0) 到 (0,1.25,-1.55),到 P 的距离恒为 1.55 |

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

1. **我的问题和事先预测。**
   - 移动相机(改 eye/target)应只改变 View,模型的世界中心数值不变;切换正交/透视只改变 Projection,同一 M/V 下画面“近大远小”的差异应只出现在透视。
   - 增大 FOV 时,透视画面中物体占比应变小;正交投影不受 FOV 影响。
   - 顶部视角若继续用 `up=(0,1,0)`,它与视线平行,`lookAt` 会退化,预期出现黑屏或 NaN。

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

3. **AI建议摘要。**
   - 控制变量一:固定 M 和 P,只改 eye/target(V);打印模型世界中心、eye/target 和 View 矩阵,观察世界中心数值不变。
   - 控制变量二:固定 M 和 V,只改 `mode`(P);在世界中放两个同尺寸、不同深度的立方体,比较屏幕占比。打印正交 m00/m55 与透视 m11(或 m55)可区分矩阵来源。
   - 控制变量三:固定 M/V,只改 FOV;只换计算参数不换相机位置。打印 `1/tan(fov/2)` 与画面占宽比。
   - 数学依据:列向量下 `p_clip=P·V·M·p`,P、V、M 的职责互不替代;透视的 w 分量随深度变化,正交 w 恒为 1。

4. **我的判断和采纳/拒绝理由。**
   - 采纳“控制变量 + 打印数值”的排查框架,因为它能区分“看起来相似”和“机制相同”。
   - 拒绝直接让 AI 生成整套程序;只让它列出可区分实验与打印量,代码由本人按本实验的 `state` 字段实现。
   - 我额外要求打印矩阵的特定元素(正交 m00、m55;透视 m55),而不是只看截图,以便用数值反推参数是否进入了矩阵。

5. **我的测试参数、测试操作与结果。**
   - Task B:初始 eye=(0,1.80,8.50)、target=(0,0,0),世界中心显示 `(0.00,0.00,0.00)`;切换正面→侧面→正面后,画面回到初始构图,世界中心始终为 `(0.00,0.00,0.00)`。顶部预设 eye=(0,8,0)、target=原点,View 矩阵全部有限,且与 `CG5Camera.safeView` 逐元素相同(差值<1e-12)。
   - Task C:Canvas 实际 aspect=1.60。正交 `orthoH=5.5` 时 `w=5.5×1.60=8.8`,得到 m00=0.2273、m55=0.3636;透视 FOV=50° 时 m55=`1/tan25°`=2.1445。同一相机与模型下切换两种 P,透视中近处立方体明显大于远处立方体,正交中两者表观尺寸基本相同。
   - 参数边界:near=0 提示“near必须大于0”;near=far 提示“far必须大于near”;FOV=180 提示“FOV必须在0°到180°之间”。把 near 从 0.1 推到 3 时,模型的近端被裁剪而消失,但世界中心数值仍为 (0.00,0.00,0.00),说明是裁剪而非删除对象。

6. **AI是否正确?我最终修正了什么认识?**
   - 三组控制变量建议正确,数值与预期一致。
   - 我原先以为“相机靠近”会让世界中心变化,实际状态栏始终显示 (0,0,0);修正为:世界坐标由 M 决定,相机只改变 V。
   - 我也确认 FOV 与 Model 缩放不等价:Model 的 scale 改变世界尺寸和世界中心以外的包围范围,而 FOV 只改变视锥张角,世界中心数值不变。

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

1. **真实错误现象和我起初怀疑的原因。**
   - 现象:按指导书实现 Shift+左拖后,正面视角向右拖模型向右移动;切到侧面视角(eye=(8,0,0))后再向右拖,模型仍沿世界 +X 移动,而不是沿当前画面的右方向移动。起初怀疑是宽高比或矩阵顺序导致“屏幕方向”换算错误。
   - 另外在自测顶部视角时,曾担心 `up=(0,1,0)` 与视线平行会导致黑屏。

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

3. **AI建议的至少两个可区分原因及测试。**
   - 假设A(宽高比):正交/透视使用了 Canvas 高度而不是 `width/height`。最小测试:读取 `aspect` 与 P 的 m00,若正交 m00 应为 `2/(orthoH·aspect)`;若误用 `2/orthoH` 则数值不同。
   - 假设B(观察基向量):Shift 拖动把像素位移直接映射到世界 X/Y,而不是相机 forward/right/up。最小测试:正面视角向右拖应改 tx;侧面视角(eye=(8,0,0))向右拖应主要改 tz。若两次都只改 tx,则问题在基向量映射。
   - 假设C(up 退化):顶部视角 `up` 与视线平行。最小测试:读取 View 矩阵是否全为有限值,或与合法 `safeView` 比较。
   - 假设D(裁剪面):near/far 未覆盖模型。最小测试:打印 near/far 与模型世界坐标,把 near 调大观察是否只发生裁剪。

4. **我实际逐项测试了什么?各自结果如何。**
   - 假设A:页面状态栏 aspect=1.60,正交 m00=0.2273=2/(5.5×1.6),与公式吻合,排除宽高比错误。
   - 假设C:顶部视角 View 全为有限值,且与 `safeView` 一致,排除 up 退化。
   - 假设D:near=0.1、far=100 时模型正常;把 near 调大只出现局部裁剪,且世界中心不变,排除“对象被删除”的误判。
   - 假设B(可恢复故障实验):临时把 Shift 分支改成“像素→世界 X/Y”并记录:侧面视角向右拖 100 px,得到位移 `(tx,ty,tz)=(1.1478,0,0)`,即沿世界 +X;恢复为相机基映射后同一测试得到 `(0,0,-1.1478)`,即沿屏幕右方向(世界 −Z)。正面视角两次测试均为 tx≈1.2466,说明错误只在相机旋转后暴露。

5. **最终根因、修复处及修复后结果。**
   - 根因:Shift 拖动没有使用当前相机的观察基,屏幕位移被硬映射到世界轴;相机变换后屏幕右方向不再等于世界 +X。
   - 修复:在 `task-d.js` 中由 eye/target 计算 `forward`、`right=cross(forward, worldUp)`、`up=cross(right, forward)`,并依据透视视锥高度或正交高度求“每像素世界长度”,再叠加 `right·dx + up·(-dy)`;同时给 eye=target 增加报错。
   - 修复后:正面与侧面拖动方向均符合“沿画面右/上方向”;滚轮只改 eye,scale 保持 1;左拖只改 rx/ry。

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

1. **我准备完成的观察任务。**
   - 以茶壶/球体/兔子为对象,在固定参考点 P 附近观察一个绕 P 公转的橙色标记,并用一个绿色小卫星标记研究“父变换之后再叠加子变换”的复合效果;要求不新增外部模型、不引入光照/纹理、不改公共框架。

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

   - 方案1:绕固定点 P 的轨道标记 + 以橙色标记为父节点的绿色卫星(父子继承)。
   - 方案2:正交/透视双画布同步对照,同一 M/V、左右只差 P,拖动时同步更新。

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

   | 对比项 | 方案1 绕点+父子卫星 | 方案2 双画布投影对照 |
   |---|---|---|
   | 功能 | 展示 `T(P)RyT(-P)` 与父子矩阵继承;保留原观察台全部能力 | 同屏对比两种 P 的表观尺寸差异 |
   | 矩阵链 | 父:`M_orbit=T(P)Ry(θ)T(-P)`;子:`M_orbit·T(q)·Ry(2θ)·T(r)·S` | 两侧共享 `M,V`,各自 `P_ortho`、`P_persp`;需第二个 GL 上下文或两次 viewport |
   | 交互参数 | 只需现有 `orbit` 滑块,联动父与子 | 需要一个同步拖动/同步相机的机制,且两个画布状态必须严格一致 |
   | 验证难度 | 低:用 `CG5.point` 打印世界坐标、验证到 P 的距离恒定 | 中高:要改 `engine.js/app.js` 增加第二画布与同步逻辑,易引入宽高比/深度状态不一致 |
   | 与本次约束 | 只改 `task-e.js`,不动公共框架 | 需改公共框架,超出“只允许更改 task-a…e 与 ai-log”的提交约束 |

4. **最终采纳的方案与理由。**
   - **本人决定采用方案1。** 理由:复用单画布的现有渲染循环与状态,矩阵链可直接由 `CG5.chain` 表达;数值验证简单(点到 P 的距离、θ=0/90 的坐标);不需要修改 `engine.js/app.js`,降低 A—D 回归风险。方案2 功能更炫,但需要第二画布和同步机制,属于 Challenge 的规模,不作为本次 E 的实现。

5. **自己实现或修改的功能差异。**
   - 实现 `ex.extra`:黄色立方体固定在 P=(0,1.25,0),橙色标记初始中心 q=(1.55,1.25,0),轨道圆与 P 同高,便于直接看出“绕 P 公转”而不是自转;16 个灰色小点画出轨道。
   - 自拟实质功能:绿色卫星以橙色标记为父节点,矩阵为 `M_orbit·T(q)·Ry(2θ)·T(0.55,0,0)·S(0.1)`。它继承父节点的公转,同时以 2θ 自转并相对父节点偏移,形成“父子继承”的复合变换;只需拖动已有的“标记绕Y旋转”滑块即可同时驱动父与子,无需新增控件。
   - 该功能完全写在 `task-e.js` 内,未改动公共框架。

6. **预测与实际结果对照,仍存在的局限。**
   - 预测:θ=0° 时橙色标记在 (1.55,1.25,0),θ=90° 时在 (0,1.25,-1.55),到 P 的距离恒为 1.55;卫星在 θ=0° 时为 (2.10,1.25,0),θ=90° 时为 (0,1.25,-1.00)。
   - 实际(用 `CG5.point` 对绘制矩阵取原点):θ=0° 橙色 (1.55,1.25,0)、卫星 (2.10,1.25,0);θ=90° 橙色 (0,1.25,-1.55)、卫星 (0,1.25,-1.0);P=(0,1.25,0)。与预测一致,说明先 `T(-P)`、再 `Ry`、再 `T(P)` 的顺序正确。
   - 局限:卫星的自转角固定为轨道角的 2 倍,没有独立滑块;P 与轨道半径按指导书固定,未新增“旋转中心输入”控件(本次提交约定只允许修改 task-a…e 与 ai-log,故未扩展 UI)。若要独立调节,需要增加状态字段和面板输入。

## 全局诚信声明

- 我提交的代码均已本人运行并核验;无法解释的AI输出未直接作为完成结果。
- AI 用于概念核对、故障假设和方案对比;矩阵实现、参数选择、故障复现与取舍由本人完成。
- 本文中的数值(归一化缩放、矩阵元素、拖动位移、轨道坐标)均来自页面状态栏或 `CG5.point` 的实际输出,不是凭空填写。