第 3 章 多重坐标空间 (Multiple Coordinate Spaces)
核心结论
-
多重坐标空间是工程必需:某些位置 / 方向只在特定参考系中已知;"绝对"坐标其实是"在我们关心的最大空间中"的坐标,并不存在真正的全局绝对。
-
常见坐标空间:world / object (model / body) / camera / upright (inertial) 四种是图形学固定词汇;"upright space"是本书引入的中间层,原点同 object space 但轴向同 world space。
-
变换的两种视角:移动坐标空间(换参考系看同一个点)vs 移动点(保持空间看点的位移)——数学等价,思维方向相反;理解两者才能在代码与公式间无缝切换。
-
基向量(basis vectors):一组线性无关向量,其线性组合 span 整个空间;任何向量 \(\mathbf{v} = x\mathbf{p} + y\mathbf{q} + z\mathbf{r}\) 可唯一表示;基向量必须 线性无关,否则不是合法基。
-
嵌套坐标空间:层级结构下,object 到 world 的变换可拆为"object → upright(旋转)"和"upright → world(平移)"两步;这是骨骼动画 / 场景图的数学基础。
-
命名即征服(name and conquer):给中间状态(upright space)命名,可让代码自解释、避免每处都写完整的旋转 + 平移;3D 引擎的 scene graph 节点就是该思想的具体化。
|
本章主旨
本章把第 1 章的"单坐标系"扩展为"多坐标系并存"。核心论点:在不同情境下使用不同坐标空间更自然;空间之间通过 坐标空间变换 互通;变换的两种视角(动空间 vs 动点)数学等价,代码侧固定采用"动点"视角;引入 upright space 作为旋转 / 平移分解的中间层。所有 3D 引擎的 scene graph、相机栈、模型 → 世界 → 投影链都遵循本章框架。 |
一、核心概念
本章围绕 6 个核心概念展开:从"为什么需要多坐标系"出发,列出常见类型,澄清变换的两种视角,引入基向量作为坐标系的代数描述,最后给出嵌套结构与代码可读性两个实践要点。
| 概念 | 定义 + 重要性 | 实现提示 |
|---|---|---|
多坐标空间的必要性 |
不同坐标系有不同的"局部信息优势"——"向东 100 米"在国家地图上有效,在你的房间内却没用。"绝对"实质上指"在最大参考系中"。 |
§3.1 论证;§3.5 进一步说明"诚实表达"重要性。把所有点都强行转 world 坐标会损失局部语义。 |
常用坐标空间 |
world / object(model / body)/ camera / upright(inertial)四类是图形学固定词汇。upright 是本书引入的中间层,原点同 object 但轴向同 world。 |
§3.2 给出定义。代码里用类型或命名空间区分(如 |
变换的双重视角 |
视角 A:"换参考系"看同一个点(空间在动,点未动);视角 B:"动点"换位置(空间静止,点在动)。两者数学等价,思维方向相反。 |
§3.3.1 详细论证;§3.3.2 给出"用另一空间的基向量表达当前空间"的精确语义。代码侧固定采用视角 B。 |
基向量 |
一组线性无关向量,其线性组合 span 出整个空间;任何向量可唯一表示为基向量的线性组合 |
§3.3.3 给出核心公式(式 3-2);§3.3.4 解释 span / rank / 线性相关。第 4 章矩阵的列就是基向量。 |
嵌套坐标空间 |
层级结构(骨骼 → 角色 → 世界);object → upright 用旋转,upright → world 用平移,组合即可表达刚体变换。 |
§3.4;动画系统中骨骼链就是嵌套空间的具体实例。scene graph 节点保存"父空间变换矩阵 + 子物体列表"。 |
命名即征服与 upright 哲学 |
Don Knuth 的"name and conquer"——给频繁使用的中间概念命名以减少噪声;upright space 就是这种命名哲学的产物。 |
§3.2.4 与 §3.5 阐述;实践上把每个变换中间结果存为命名变量,代码可读性显著提升。 |
二、详细笔记
2.1 多坐标空间的必要性 (Why Multiple Spaces)
What:3D 图形中,不同情境下使用不同的坐标系更自然;不存在真正的"绝对位置","绝对"= "在我们关心的最大空间中"。
Why:把所有点都强制转 world 坐标会损失局部语义(如"角色前方"),并且当某些信息只在局部可知时,强行转换是不可能的。
How:
-
多空间的好处:每个空间保留最自然的描述;信息只在局部空间可知时无需"求全";多人协作时各管各的局部空间,最后统一到 world。
-
Cartesia vs Dyslexia 例子(§3.1):两座城市各有自己的地图;州交通工程师要做跨城公路,必须引入第三张图——这就是第三坐标系出现的合理动机。
-
"绝对"的真实含义:并非字面意义上的"全球唯一",而是"在我们关心的最大参考系(通常是 world)中的坐标"。
|
历史先例
|
When:大型场景(角色 + 道具 + 地形)必须分层;UI 元素单独在自己空间(屏幕坐标);骨骼动画必然嵌套。
Example:一个角色跑过场景——世界坐标描述"在地图哪里",角色坐标描述"在角色前方还是后方",相机坐标描述"在相机视野哪里";同一时刻用三个空间并存描述最自然。
2.2 常用坐标空间 (Common Coordinate Spaces)
What:4 类基础坐标空间——world、object(model / body)、camera、upright(inertial)——是图形学固定词汇。
Why:跨引擎 / 跨论文交流时,固定词汇避免歧义;每种空间有默认轴向与原点约定。
How:
四种空间的核心特征:
-
world space:全局参考系;原点是"我们关心的最大范围"的中心;其他空间都可用 world 表达,但 world 自己不被更大的空间表达(除非引入银河系、太阳系等更大的概念)。
-
object space(model / body):每个物体自带;物体移动 / 旋转时,其 object space 跟着移动 / 旋转。模型顶点存的就是 object space 坐标。
-
camera space:一种特殊的 object space,原点在相机、+x 右、+y 上、+z 前(左手系传统);OpenGL 习惯右手系(+z 朝向你)。
-
upright space:本书命名——原点同 object space,轴向同 world space。用来把"旋转"和"平移"在概念上分离。
|
upright space 的命名之争
本书第一版用 "inertial space",但与物理学的"惯性参考系"含义不同,故改名 upright。物理中类似概念叫"质心坐标"。这是一个"好的概念等待好名字"的例子(§3.2.4、§3.5)。 |
When:建模代码(object)、场景图(world)、视图 / 投影(camera)、中间缓存(upright)各司其职。
Example:机器人模型顶点存的是 object space;动画师想"让机器人向东走 10 米",是 upright → world 的平移;最终渲染时再 object → world → camera → screen。
2.3 变换的双重视角 (Dual Perspectives)
What:坐标空间变换有两种等价思维——"换参考系"(空间在动,点未动)vs "动点"(空间静止,点在动)。
Why:理解两种视角才能在代码与公式间切换;数学推导常用视角 A(基向量替换),代码实现固定视角 B(点矩阵乘)。
How:
-
视角 A(换参考系):点未动,描述它的参考系换了。例:"机器人向东走 10 米"等价于"在世界空间里,机器人从
(0,0,0)移到 `(10,0,0)`"——描述不变,空间变换。 -
视角 B(动点):空间静止,点在新空间中的坐标变了。例:把机器人的脚从
(0,0,0)转到(10,0,0)——空间未动,点在新坐标中位移。
数学上的统一:把"基向量"作为"空间的别名"——视角 A 中替换基向量就是视角 B 中改写点坐标。两者在数学上完全等价。
When:
-
公式推导(点积 / 叉积 / 矩阵变换)通常在视角 A 下表达"用哪组基向量"。
-
代码实现(C++ / GPU shader)固定视角 B:给定变换矩阵
M,点变换p' = M p。 -
数学直觉遇到困惑时,回到"动点"视角就能落地。
Example:机器人从 origin 出发,先 旋转 120° 再 平移 [18, 0, 10]。视角 A 说:"原点 + 基向量同步变换";视角 B 说:"点坐标先旋转再平移"。两者结果一致。
2.4 基向量与坐标空间描述 (Basis Vectors)
What:一组线性无关向量 p, q, r 称为该空间的基向量;任何向量 \(\mathbf{v}\) 可唯一表示为基向量的线性组合 \(\mathbf{v} = x\mathbf{p} + y\mathbf{q} + z\mathbf{r}\)。
Why:基向量是"用另一空间描述本空间"的代数工具;第 4 章矩阵的列就是基向量的具体化。
How:
式 3-2(线性组合):
基向量的关键性质:
-
线性无关:没有向量能写成其他向量的线性组合;否则坐标不唯一。
-
span:基向量的所有线性组合构成的空间;n 个基向量最多 span n 维("full rank");少于 n 即 线性相关。
-
坐标依赖于基:\(\mathbf{p}, \mathbf{q}, \mathbf{r}\) 在 自己空间 中永远是
[1,0,0], [0,1,0], [0,0,1],但在 另一空间 中是任意值。
|
基向量的常见误区
"基向量一定是 `[1,0,0], [0,1,0], [0,0,1]`"——错。这只在"用基向量所在空间描述自身"时成立。换到另一空间,基向量可以是任意坐标。这是基向量和坐标"看起来一样"的迷惑性根源。 |
When:纹理映射的切线 / 副切线 / 法线(tangent / binormal / normal)就是 不一定正交的 基向量特例;§10.9 bump mapping 详细展开。
Example:物体空间的基向量在物体空间中是 [1,0,0] / [0,1,0] / [0,0,1];在 world 空间中可能是 [0.866, 0, 0.5] / [0, 1, 0] / [-0.5, 0, 0.866](绕 y 旋转 30° 后)。
2.5 嵌套坐标空间 (Nested Coordinate Spaces)
What:层级结构(物体 → 父物体 → … → 世界)下,每层的变换矩阵把子空间映射到父空间;嵌套展开就是累积变换链。
Why:骨骼动画、关节链、场景图都基于此;理解嵌套才能正确处理"物体跟着父物体移动"的现象。
How:
把 object → world 分解为两步(式 3-1 的一般化):
-
object → upright:旋转(轴向对齐)。
-
upright → world:平移(原点对齐)。
一般化的"object → parent → grandparent → world"链:每层变换是一个矩阵;总变换 = 连乘。
|
分解的好处
把"旋转 + 平移"分解为两步的好处:旋转在原点的局部空间内做,几何上等价于"先转基向量再放点",参数(旋转轴 / 角度)更直观;平移用向量加法即可,参数更直观。两者合一("旋转 + 平移混合矩阵")虽然紧凑但容易出错。 |
When:骨骼动画(每根骨头有自己的 object space,相邻骨头靠 joint 连接);UI 树(屏幕空间嵌套);粒子系统(粒子在父物体空间定义,跟随父物体运动)。
Example:机器人举手臂——上臂的 object space 在肩膀位置;前臂的 object space 在肘部位置(相对于上臂);手掌的 object space 在腕部位置(相对于前臂)。整条链最终展开到 world。
2.6 命名即征服与 upright 哲学 (Name and Conquer)
What:Don Knuth 的"name and conquer"——给频繁使用的中间概念命名以减少代码噪声;本书的 upright space 就是这种命名的具体化。
Why:每处都写完整旋转 + 平移会让代码 / 文档臃肿;命名中间状态既可读又可测。
How:
-
命名中间结果:把"旋转量"命名为
orientation、"位置"命名为position、"半步结果"命名为upright_pos,比"旋转矩阵 R"和"平移向量 T"分写再相乘更易理解。 -
upright space 的命名理由:它是"既知道物体原点在哪、又知道世界轴向"的中间空间——很多中间计算自然落在它上面。
-
代码可读性:把
M = T * R; p_world = M * p_obj;改成M = compose(rotation, translation); auto p_upright = rotate(p_obj, rotation); auto p_world = translate(p_upright, position);显著更易调试。
When:所有"多步组合"的场景——动画合成、相机栈、复合碰撞检测。
Example:骨骼动画导出格式(FBX / glTF)通常存的是"局部旋转 + 父索引",运行时引擎自动展开嵌套——这正是 upright 哲学的工程实例。
三、关键图表
视觉图表
非可视化条目
|
非可视化条目(表 / 算法)
|
核心公式对照表
|
核心公式对照表
|
四、思维导图
mindmap
root((第 3 章 多重坐标空间))
多空间必要性
局部信息优势
绝对是相对最大空间
历史先例
常见空间
world全局
object物体
camera相机
upright中间层
变换双重视角
换参考系
动点
数学等价
基向量
线性无关
span
坐标依赖基
嵌套空间
旋转加平移
骨骼链
累积变换
命名即征服
upright哲学
代码可读
中间结果命名
五、重点与易错点
-
不存在"绝对"位置:"绝对"实质是"在最大参考系中";超出关心的范围(地球 vs 太阳系 vs 银河系)就换基向量。
-
upright space 是本书命名:与物理的"惯性参考系"含义不同;本质是"原点同物体、轴向同世界"的中间层,便于把旋转与平移概念分离。
-
变换的双重视角数学等价:视角 A 替换基向量 = 视角 B 改写点坐标;公式推导用视角 A,代码实现固定视角 B。
-
基向量不一定是
[1,0,0]/[0,1,0]/[0,0,1]:在自己空间成立,在其他空间是任意值;这是初学者最易混淆之处。 -
基向量必须线性无关:相关时坐标不唯一(如
r = a就线性相关);n 个相关基向量 span 不到 n 维。 -
upright 在原点的局部空间:分解为"先旋转对齐基向量"与"再平移对齐原点"两步;混在一起用 4×4 矩阵虽紧凑但难调试。
-
嵌套空间 = 变换链:父子空间间靠变换矩阵链接;总变换 = 各级矩阵连乘;骨骼动画的"局部旋转 + 父索引"格式就是嵌套思想的具体化。
-
camera space 的两种约定:DirectX / Unity 左手(+z 前 / 远离你),OpenGL 右手(+z 朝向你 / 远离屏幕);跨引擎时第一件事是确认朝向。
-
代码可读性 = 命名中间结果:避免"4×4 矩阵连乘一行"——拆成
orientation * translation+ 中间变量,调试时单步检查每一级。 -
跨章衔接:第 4 章把基向量代数化为矩阵的列;第 5 章把"先旋转再平移"封装为矩阵乘法;第 8 章讨论多种旋转表示(欧拉角 / 轴角 / 四元数);第 10 章展开 camera space 到 screen space 的投影链。