AI 协作日志

学生 Web 实验作品平台

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

# 实验二 AI 协作记录

**实验:** 计算机图形学实验二 · WebGL 图案生成与交互设计
**AI 工具:** TRAE(对话式 AI 编程助手)
**说明:** 本文件记录三次关键协作闭环,含提示词、个人判断、测试方法与修正结论。核心代码经过独立理解与浏览器实际运行验证。

---

## AI 协作 1:Koch 算法 —— 确认外凸旋转方向(Task B)

### 我的目标与初步判断

实现 Koch 雪花的核心难点是:如何确保等边三角形顶点 R 向外凸起(而不是向内凹陷)。初始三角形顶点为逆时针排列 `[[-0.82,-0.43],[0.82,-0.43],[0,0.99]]`,我通过叉积确认了这个方向:

```
(B-A) × (C-A) = (1.64, 0) × (0.82, 1.42) = 1.64×1.42 > 0  → 逆时针 ✓
```

**个人初步判断:** 沿逆时针方向行走时,边 AB 的"外侧"在右侧。所以 PQ 向量应该**顺时针旋转 60°**(右转)得到向外的顶点 R。我先手写了顺时针旋转公式:
```
R = P + rotate(PQ, -60°)
rotate(x,y,-60°) = (x·cos60 + y·sin60, -x·sin60 + y·cos60)
                  = (x·0.5 + y·√3/2, -x·√3/2 + y·0.5)
```

### 关键提示词(保留原文)

> 我正在实现 WebGL 的 Koch 雪花算法。初始三角形顶点是逆时针排列的 baseTriangle = [[-0.82,-0.43],[0.82,-0.43],[0,0.99]]。对于每条线段 A→B,我需要计算向外凸出的等边三角形顶点 R。我计划把 PQ 向量顺时针旋转 60°(右转)加到 P 上得到 R。请帮我验证这个方向是否正确,以及如果我搞反了会看到什么图案现象。

### AI 关键建议摘要

AI 确认了我的思路是对的,但补充了几个关键点:

1. **旋转方向公式验证:** 逆时针排列的简单多边形,每条边的外法线方向与边方向向量成 `-90°`。将 PQ 顺时针旋转 `60°` 等价于 `外法线方向 × |PQ| / cos(30°)` 的近似,最终确实指向外部。
2. **水平边特例测试:** AI 建议用水平边 A=(-1,0), B=(1,0) 快速验证。对于这条边,外凸应该得到 R 在 (0, -√3/3) —— 因为这条边的外面是下方(三角形内部在上方)。
3. **递归终止条件:** AI 提醒如果用 LINE_LOOP 绘制,最后一条线段的终点会自动连回第一条的起点,所以 buildKoch 里不必单独 push 终点。

### 我的测试方法与结果

**测试 1 —— 水平边特例验证:**

```
P = (-1/3, 0), Q = (1/3, 0)
PQ = (2/3, 0)
R = P + (2/3·0.5 + 0·√3/2, -2/3·√3/2 + 0·0.5)
  = (-1/3 + 1/3, -√3/3) = (0, -√3/3) ≈ (0, -0.577)
```

运行 Task B,Level 0 时三角形底边确实是水平的(y=-0.43),Level 1 后底边中点下方出现凸起 → **向外 ✓**。如果我用了逆时针旋转(方向搞反),凸起会跑到三角形内部 → 视觉上会看到"凹进去"的 Koch 雪花。

**测试 2 —— 各 Level 线段数验证:**

| Level | 预期 3×4ⁿ | 实际输出 |
|-------|-----------|----------|
| 0     | 3         | 3        |
| 1     | 12        | 12       |
| 2     | 48        | 48       |
| 3     | 192       | 192      |
| 4     | 768       | 768      |

Chrome Console 中 `stats.textContent` 实时显示的数值与预期完全一致。

### 是否采纳、修正后的结论

✅ **完全采纳** AI 确认的顺时针旋转公式,最终代码:

```javascript
const r = [
  p[0] + dx*0.5 + dy*Math.sqrt(3)/2,
  p[1] - dx*Math.sqrt(3)/2 + dy*0.5
];
```

最终效果:Level 0—4 均得到向外凸起的闭合 Koch 雪花,不裁切,形状正确。

---

## AI 协作 2:交互绘图调试 —— 人为制造错误再修复(Task D)

### 具体错误现象

Task D 写好后运行正常(点击 Canvas 能准确在鼠标位置绘制点/线/矩形)。为了完成协作记录,我**人为制造了一个错误**来模拟调试过程。

### 我的初步排查

**故意引入的错误:** 删除坐标转换代码中的 Y 轴翻转步骤。原始代码:
```javascript
return [2*xCanvas/canvas.width - 1, 1 - 2*yCanvas/canvas.height];  // 正确
```
**改为:**
```javascript
return [2*xCanvas/canvas.width - 1, 2*yCanvas/canvas.height - 1];   // 故意错误:Y 未翻转
```

### 关键提示词(保留原文)

> 我的 WebGL 绘图板 Y 轴搞反了。点击 Canvas 顶部,图形出现在底部;点击底部,图形出现在顶部。我怀疑是 Y 轴翻转的问题。请列出可能的原因清单和逐项排查步骤。不要直接给代码修复,让我自己一步步测。

### AI 建议及逐项测试

AI 给出的排查步骤(我逐项验证):

| 优先级 | 检查项 | 我的测试 |
|--------|--------|----------|
| 1 | `yCanvas = (event.clientY - rect.top) * canvas.height / rect.width` — 宽高搞反? | ✅ 不是,我的宽高没搞反 |
| 2 | NDC Y 翻转公式是否写成 `2y/h - 1` 而非 `1 - 2y/h` | ❌ **就是这个!** 我的故意错误正好对应这个问题 |
| 3 | Canvas CSS 尺寸 vs 像素尺寸是否一致 | 一致(720×620) |
| 4 | Fragment Shader 里是否有额外的 Y 方向变换 | 没有 |
| 5 | `gl.viewport` 设置是否正确 | `gl.viewport(0,0,canvas.width,canvas.height)` ✓ |

**修复:** 把故意错误的 `2*yCanvas/canvas.height - 1` 改回 `1 - 2*yCanvas/canvas.height`,刷新页面后点击位置与图形位置完全一致。

**附加测试:**
- ✅ 调整浏览器窗口大小后再点击 Canvas 中心 → 位置准确
- ✅ 切换工具(点→线→矩形)再点击 → 状态正确重置
- ✅ 先画一点、一线、一矩形 → 旧图形不消失
- ✅ 清空后重新绘制 → 旧图形不再出现

### 最终原因与修复证据

**根因:** NDC 坐标系统 Y 轴向上(1 在顶部,-1 在底部),但屏幕像素坐标 Y 轴向下(0 在顶部)。转换必须翻转:`yNDC = 1 - 2*yCanvas/canvas.height`。省略 `1 -` 就会导致上下颠倒。

**修复后 Console 证据:** 在 Canvas 四角点击,打印 NDC 值:
```
点击左上角  → NDC(-0.98, 0.98)  ≈ 预期 (-1, 1)  ✓
点击左下角  → NDC(-0.98,-0.98)  ≈ 预期 (-1,-1)  ✓
点击右上角  → NDC( 0.98, 0.98)  ≈ 预期 ( 1, 1)  ✓
点击右下角  → NDC( 0.98,-0.98)  ≈ 预期 ( 1,-1)  ✓
```

---

## AI 协作 3:主题化整合 —— 两种方案比较(Task E)

### 主题与预期效果

**主题词:** 绽放
**预期效果:** 用 Koch 雪花作为花瓣轮廓,辅以装饰性几何元素(外环、放射线、节点),点击 Canvas 可移动图案中心,滑块可调整展开尺度。旋转动画象征动态绽放过程。

### 提示词(保留原文)

> 我要做一个"绽放"主题的 WebGL 作品。已经有 Task B 的 Koch 雪花算法和 Task C 的 uniform 旋转动画。请给我两种可行方案,分别说明:
> 1. 每种方案新增哪些几何组成(顶点数量级、图元类型)
> 2. 新增哪些交互方式
> 3. 实现难度对比
> 4. 可解释性(为什么符合"绽放"主题)
> 我需要从中选一种实际实现。

### AI 提出的可选方案

**方案 A —— 放射绽放(我采纳的方案):**

| 维度 | 内容 |
|------|------|
| 复用 | Koch 雪花(Task B)+ uniform 旋转(Task C) |
| 新增几何 | ① 外环(96 段 LINE_LOOP,~192 顶点)② 12 条放射线(24 顶点)③ 12 个节点(12 POINTS) |
| 新增交互 | 点击 Canvas 改变图案中心;滑块调整缩放 |
| 可解释性 | Koch 花瓣从中心向外绽放,放射线象征光芒,节点标记关键位置 |
| 实现难度 | 低,约 30 行新增代码 |

**方案 B —— 层级绽放:**

| 维度 | 内容 |
|------|------|
| 复用 | Koch 雪花(Task B)+ uniform 旋转(Task C) |
| 新增几何 | ① 多层嵌套的 Koch 雪花(每层独立绘制,各用不同颜色和缩放)② 中心装饰圆 |
| 新增交互 | 滑块控制"绽放层数"(1-4 层);每层可独立旋转 |
| 可解释性 | 从内到外逐层绽放的花结构 |
| 实现难度 | 中,需要管理多个 uniform 组 |

### 方案取舍与理由

**采纳方案 A。** 理由:

1. **可解释性清晰:** 外环(光晕)+ 放射线(光芒)+ 节点(端点标记)三种新增几何都能直观对应"绽放"的视觉含义
2. **顶点数可控:** 总新增顶点 ~230,远小于 Level 4 Koch 雪花本身的 768 顶点,不会有性能问题
3. **交互简洁:** 点击改中心 + 滑块改缩放,两种交互都有实际效果
4. **符合任务要求:** 明确复用了 Task B(Koch 生成)+ Task C(旋转控制)两项能力,新增了外环、放射线、节点三个几何组成

**拒绝方案 B 的理由:** 多层 Koch 雪花虽然视觉上更华丽,但本质上只是重复调用 buildKoch 并多次 drawArrays,对"独立新增几何组成"这一评分点来说不够有区分度。而且多层同时旋转容易造成视觉混乱,调试成本更高。

### 实际实现与验证结果

**最终效果:**

```
每帧绘制顺序:
  1. 外环 (LINE_LOOP, 96 顶点, 固定位置)
  2. Koch 雪花 (LINE_LOOP, 随 Level 变化, uniform 旋转)
  3. 放射线 (LINES, 24 顶点, 跟随旋转)
  4. 节点 (POINTS, 12 顶点, 跟随旋转)
```

**交互验证:**
- ✅ 点击 Canvas 任意位置 → 图案中心移到点击处
- ✅ 调整"装饰图案层数"滑块 → Koch 重新生成
- ✅ 调整"展开尺度"滑块 → 整体缩放
- ✅ 点击"开始/暂停旋转" → 动画启动/停止
- ✅ 点击"复位" → 全部状态恢复默认

**设计说明(页面上 200 字限制):**

> 主题:绽放。复用 Task B 的 Koch 雪花算法(花瓣轮廓)和 Task C 的 uniform 旋转动画。新增三个几何组成:①外环(光晕)②12条放射线(光芒)③12个节点(端点标记)。两种交互:点击 Canvas 移动图案中心、滑块调整展开尺度。动画运行时内外层同步旋转,象征花朵在时光中绽放。

---

## 其他实际使用的 AI 协作(如有)

### 工具、提示词及关键处理说明

在写代码前,我让 AI 帮我**预演了一遍完整的坐标转换流程**(Task D),确保公式正确。提示词:

> 帮我手动走一遍 Task D 的坐标转换。假设 canvas 720×620,用户点击 (360, 310)(正中心),算一下:rect.left, rect.top, xCanvas, yCanvas, xNDC, yNDC 分别是多少。

AI 预演结果:
```
rect.left = rect.top = 0(没有 CSS 外边距时)
xCanvas = 360 * 720 / 720 = 360
yCanvas = 310 * 620 / 620 = 310
xNDC = 2*360/720 - 1 = 0  ✓
yNDC = 1 - 2*310/620 = 0  ✓
```

我在浏览器 Console 里点击中心点验证,输出 NDC 确实是 (0, 0)。这一步帮助我在写代码前就确认了公式的正确性,避免了后面运行时反复调试。

---

**记录人:** (填写本人学号和姓名)
**日期:** 提交日期