# 实验四说明与结果

## 1. 变换约定

本实验采用右手坐标系和列向量。顶点在 Vertex Shader 中按 `uProjection·uView·uModel·position` 变换，所以 `M=T·R·S` 的实际作用顺序是先缩放、再旋转、最后平移。几何 Buffer 初始化一次，各对象绘制时只更换 Model uniform。

## 2. 各任务实现

### Task A

模型矩阵为 `T(tx,ty,tz)·Ry(theta)·S(s)`。局部原点经过缩放与旋转仍为原点，因此世界中心只由平移决定。验收参数 `tx=1、ty=0、tz=0、theta=90°、s=1` 得到中心 `(1,0,0)`；改变 s 不改变中心。

### Task B

两个对象共享几何和 Shader，只改变 Model 矩阵：`M1=T·Ry·S`，`M2=Ry·T·S`。局部原点的独立预测分别是 `(tx,0,0)` 和 `(tx cosθ,0,-tx sinθ)`。`tx=2、theta=90°` 时实测为 `(2,0,0)` 与 `(0,0,-2)`。

### Task C

自转为 `T(q)·Ry(theta)·S`；绕任意世界点 P 旋转为 `T(P)·Ry(theta)·T(-P)·T(q)·S`。动画按 `angle += speed·dt` 更新，暂停时 angle 不再累加。非原点测试 `P=(1,0,1)`：90°中心为 `(0,0,0)`，360°回到初始中心 `(2,0,0)`。

### Task D

`Mbase=T(basePos)·Ry(yaw)`，`Mshoulder=Mbase·T(0,h,0)·Rz(pitch)`，`Mtip=Mshoulder·T(0,L,0)`。臂段的非均匀缩放只放入 `Marm`，没有继续传给 Mtip，否则探头的位置和大小都会被错误拉伸。yaw=90°、pitch=-30°时臂端实测 `(0,1.16,-1.10)`，独立公式预测相同；只反转 pitch 后肩点不变，臂端变为 `(0,1.16,1.10)`。

### Task E

自主主题为“双关节自动检测工作台”。在教师参考的肩部结构上新增肘关节和探头伸缩，构成基座→肩→上臂→肘→前臂→腕→探头的层级。右侧样本同时提供自转与环绕标记公转。页面有 yaw、肩角、肘角、伸缩量、速度五个参数，支持暂停、继续、重置、两个核验预设和 PNG 导出。

### Challenge

额外实现可解释复合变换实验台，对比 `T·R·S`、`R·T·S`、`T·S·R`、`S·R·T`。使用非均匀缩放 `(sx,1,sz)`，同时观察局部原点 O 和非中心点 P=(1,0,0)，避免“中心相同就误判矩阵相同”。解析坐标公式与 gl-matrix 的矩阵结果共核验 1944 个点，最大误差约 `1.91e-7`。

## 3. 思考题回答

1. `T·R·S` 右侧先作用，因此顶点先经过 S，再经过 R，最后经过 T。
2. `R·T` 会旋转已经平移后的坐标，平移向量也随之改变方向；`T·R` 的最后平移保持世界轴方向。
3. 可把局部原点或非中心点 `(1,0,0)` 代入 Model 矩阵，比较世界坐标与独立公式。
4. 自转保留物体中心平移在最左侧；绕 P 公转需要 `T(P)·R·T(-P)` 包住物体原始世界位姿。
5. `T(-P)` 把旋转中心搬到原点，R 才能围绕它旋转，随后 `T(P)` 恢复世界位置。
6. 子位姿左乘父位姿，所以父变化会传给子；父矩阵不依赖子矩阵，因此子变化不影响父。
7. 若把拉长臂段的 S 传给下一层，探头的局部平移、大小也会被缩放，装配关系会失真。
8. 多对象复用 Buffer 和 Shader，逐次上传各自的 `uModel` 后绘制。
9. 每帧从参数重建矩阵可避免数值漂移，也使暂停、重置和控制变量测试更明确。
10. 当画面和坐标冲突时，应先信可手算的测试点，固定其他变量，打印矩阵与中心，再逐项检查角度单位、相乘顺序和坐标系。
