第 1 章 笛卡尔坐标系 (Cartesian Coordinate Systems)

      +

      核心结论

      • 3D 数学的根基是笛卡尔坐标系:通过原点、轴与有符号距离,把 3D 空间中"位置 / 距离 / 角度"的连续直观问题转化为代数计算。

      • 1D→3D 是递进而非对称的:所有 2D 坐标系都可通过旋转对齐(无手性问题),但 3D 存在左手 / 右手两套不可旋转对齐的体系,这是后续矩阵 / 四元数 / 叉积符号差异的源头。

      • 数值精度是工程权衡:C++ 中 short / int / float / double 全是离散的,选型本质是精度权衡而非"离散 vs 连续"。书中"第一法则"——If it looks right, it is right.——把可视化验证置于数值严格性之上。

      • 左手 vs 右手只差一个负号:把任意一个轴反向即可切换手性,对绝大多数公式影响仅在 z 相关的符号上;但旋转"正方向"由对应手性的手指定则决定,混淆会导致旋转矩阵列序与叉积方向全错。

      • 本书用左手系:+x=右、+y=上、+z=前(屏幕里则 +z=外);数学身份式在任何手性下都成立,但应用到旋转 / 投影时需明确差异。

      • 数学预备集中于 §1.4:求和 / 区间 / 角度(度 vs 弧度)/ 三角函数与恒等式——后续章节默认读者掌握,不再展开。

      本章主旨

      本章是全书的"约定章"。它不引入新的 3D 工具,而是建立后续 12 章都要复用的词汇与坐标系惯例:从数系复习 → 2D 笛卡尔 → 3D 笛卡尔 → 左手 / 右手手性 → 全书采用的左手系约定 → 数学预备速览。第 2 章起的向量、矩阵、变换都是在这些约定之上展开。

      一、核心概念

      本章围绕 6 个核心概念展开:先从 1D 数系复习建立"连续 vs 离散"的工程直觉,再逐步上升到 2D / 3D 笛卡尔坐标系,然后用手性区分不可对齐的 3D 体系,最后约定本书惯例并补齐数学预备。

      概念 定义 + 重要性 实现提示

      数系与精度

      自然数 → 整数 → 有理数 → 实数的层级;C++ 中 short/int/float/double 均为有限离散表示,精度取决于位宽。直接关联 §1.1 第一法则:"看起来对就是对的"。

      选择 float 还是 double 是工程决策;图形硬件偏好 float,物理仿真与累积运算偏好 double 以减小漂移。

      2D 笛卡尔空间

      由原点 + 两条互相垂直的轴构成,点的位置用 (x, y) 有符号距离表示。轴的方向可任意选取(屏幕坐标系常 +y 向下)。

      §1.2 完整定义;§1.2.3 给出"点到点的距离公式"前置;后续 2D 图形 / UV 坐标全部依赖此抽象。

      3D 笛卡尔空间与坐标平面

      增加第三条轴 z,三轴两两垂直。两轴确定一个坐标平面:xy / xz / yz;任意平面本身也是合法的 2D 子空间。

      §1.3.1 引入三平面;§1.3.2 把 2D 的"有符号距离"推广到 3D——点的 x 是到 yz 平面的有符号距离。

      手性与坐标系方向

      所有 3D 坐标系分两类:左手 / 右手。同手性可旋转对齐,异手性不可——只能通过反转一个轴切换。

      §1.3.3 用手指给出"手性判定";表 1.1 列出三轴正方向的旋转映射(左手顺时针 / 右手逆时针)。后续矩阵列序、叉积方向、-z 是否出现在投影公式中均由此决定。

      本书的坐标惯例

      左手系;+x=右、+y=上、+z=前;地理场景下 +x=东、+z=北。该惯例与 Unity 一致,与 OpenGL / DirectX 默认右手系需做 z 翻转。

      §1.3.4 全文约定;后续旋转公式默认按左手系推导,使用右手系 API 时要在投影矩阵里加 z 翻转。

      数学预备:求和 / 区间 / 弧度 / 三角

      求和符号 Σ、区间记法 [a, b]、弧度与角度互换 1 rad = (180/π)°、三角函数基于单位圆的定义以及毕达哥拉斯 / 和差恒等式。这些是后续向量 / 矩阵推导的脚手架。

      §1.4 速览;公式表 1.2 给出常用角度的三角值;式 1-1 给出和差恒等式,后续向量点积 / 叉积推导会引用。

      二、详细笔记

      2.1 数系与精度 (Number Systems & Precision)

      What:从自然数 → 整数 → 有理数 → 实数的层级,以及在计算机中以有限位宽近似实数带来的精度选择问题。

      Why:3D 图形看似处理连续实数,但 GPU / CPU 只能存有限离散值。"看起来对"之所以成为第一法则,就是因为最后要把实数误差折算成"屏幕上看不出来"。

      How

      C++ 数据类型的有效位宽(按当前 PC 约定):

      类型 容量

      典型用途

      short

      16 bit,约 65 536 值

      不适合 VR;偶用于 packed vertex buffer

      int

      32 bit,约 43 亿值

      索引 / 像素坐标足够

      float

      32 bit,约 43 亿离散有理子集

      顶点 / 法线 / 颜色;GPU 原生类型

      double

      64 bit,更高密度

      第一法则(First Law of Computer Graphics):If it looks right, it is right.——在 3D 视觉场景下,肉眼不可见的浮点误差可被接受,远比追求数值的严格正确重要。

      When:选 float vs double 时——若需要长时间累积(积分 / 物理链式变换)或精度敏感(碰撞检测、布尔运算),用 double;若每帧每顶点多次矩阵乘法且需要带宽,用 float

      Example:在 830 页长篇里,作者风趣地把"零"和"负数"的发明归功于"卖不存在的羊的快嘴商人"——但工程上 负数 是向量取反与矩阵奇异性判定的关键。

      2.2 2D 笛卡尔空间 (2D Cartesian Space)

      What:由原点(origin)与两条过原点的轴(x 轴 / y 轴)构成的平面框架;点的位置由 (x, y) 两个有符号距离唯一确定。

      Why:所有 2D 渲染(屏幕像素、纹理 UV、地图、棋盘)都基于此抽象。把"现实中的位置"映射为"两个数"是图形编程的第一步。

      How

      2D 笛卡尔坐标系的关键要素:

      • 原点:坐标系的"中心",是两条轴的唯一交点。

      • 两条互相垂直的轴:通常记 x 轴(水平)与 y 轴(垂直),正向由约定确定。

      • 点的坐标P = (x, y),其中 x 是点到 y 轴的有符号距离,y 是点到 x 轴的有符号距离。

      轴向约定的多样性

      约定不唯一:

      • 数学标准:+x=右、+y=上。

      • 屏幕坐标:+x=右、+y=下,原点在左上角。

      • 地图坐标:可任意旋转 / 翻转(如图 1.7 所示 8 种 2D 方向)。

      在 2D 中,任意两个坐标系都可以通过旋转 / 镜像对齐——即"所有 2D 坐标系都等价"。这是 §1.3.3 进入 3D 时要颠覆的关键直觉。

      When:用 2D 笛卡尔表示平面几何(屏幕像素、纹理采样、地图投影);用 极坐标(第 7 章)表示方向 / 距离分离的物理量(雷达、声音、旋转)。

      Example:Cartesia 城用 "East 2nd Street / North 4th Street" 命名街道,对应 (x=2, y=4)。从 (2, 4)(-2, -3) 的位移即 (-4, -7),向南 7 街 / 向西 4 街。

      2.3 3D 笛卡尔空间与坐标平面 (3D Cartesian Space & Coordinate Planes)

      What:在 2D 基础上增加第三条轴 z,三轴两两垂直;任意两轴确定一个 2D 坐标平面(xy / xz / yz),三平面两两垂直。

      Why:从 2D 到 3D 不是"再加 50% 复杂度"——它引入了手性(§2.4),这一性质在 2D 中不存在。但 3D 任意坐标平面本身仍是合法的 2D 笛卡尔空间,可以独立分析(如地面 = xz 平面)。

      How

      3D 笛卡尔坐标系的关键扩展:

      • 第三条轴 z:与 x、y 都垂直,正方向由约定确定(左手 +z=前;右手 +z=外)。

      • 三平面xy / xz / yz;每个平面包含两条轴,垂直于第三条。

      • 3D 点定位(x, y, z)x 是到 yz 平面的有符号距离(沿平行于 x 轴的直线测量),y 是到 xz 平面的有符号距离,z 是到 xy 平面的有符号距离。

      3D 不再是 2D 的简单叠加

      2D 中"所有坐标系等价"靠旋转即可对齐;3D 中存在两种 不可 通过旋转对齐的坐标系——左、右手系(§2.4)。这导致从 2D 直觉推导 3D 时,"看起来一样"的运算可能差一个负号。

      When:3D 笛卡尔是第 2 章起所有内容的坐标系;坐标平面常用于把 3D 问题降维(如把角色动画投影到 xy 屏幕平面分析)。

      Example:把 +x、+y、+z 分别赋为右、上、前时,"地面"就是 xz 平面(y=0),角色在地面上跑步等价于 2D xz 平面问题。

      2.4 手性与坐标系方向 (Handedness)

      What:3D 坐标系分左手系与右手系;同手性可旋转对齐,异手性只能通过翻转一个轴切换。正向旋转的方向(左手顺时针 / 右手逆时针)由对应手的手指定则(hand rule)给出。

      Why:手性决定了叉积方向、旋转矩阵列序、欧拉角旋转符号、z 是否在投影公式中带负号——一旦混淆,所有旋转 / 朝向 / 法线方向的代码都会与可见结果相反。

      How

      手性判定("手指定则"):

      • 左手系:左手拇指=+x、食指=+y、中指=+z;观察轴正向时,正向旋转是 顺时针

      • 右手系:右手拇指=+x、食指=+y、中指=+z;正向旋转是 逆时针

      • 等价切换:反转任意一个轴的正方向(左 ↔ 右切换);交换两个轴等价于绕第三个轴旋转 180°,手性不变。

      式 1-1 给出的手性差异——卡迪尔轴上的正向旋转映射:

      \[\begin{array}{c|ccc} \text{绕轴} & \text{左手正方向} & \text{右手正方向} \\ \hline +x & +y \to +z \to -y \to -z \to +y & +y \to -z \to -y \to +z \to +y \\ +y & +z \to +x \to -z \to -x \to +z & +z \to -x \to -z \to +x \to +z \\ +z & +x \to +y \to -x \to -y \to +x & +x \to -y \to -x \to +y \to +x \\ \end{array}\]

      When:写旋转矩阵 / 叉积 / 法线变换时,永远先问"当前手性是什么";跨引擎复用代码时(Unity 左手 ↔ OpenGL 右手),第一件事是在投影矩阵加 z 翻转。

      Example:用右手系做 cross(forward, up),若得到 right,那么在左手系中要改成 cross(up, forward) 才能得到 right

      2.5 本书的坐标惯例 (Book Conventions)

      What:本书采用左手系;+x=右、+y=上、+z=前;地理场景下 +x=东、+z=北。

      Why:全书公式按此推导;复用本书代码到右手系(OpenGL / DirectX)时,需要把 z 翻转或调整矩阵列序。

      How

      • 左手系:与 Unity 渲染管线默认一致;与 OpenGL / 传统线性代数默认的右手系相反。

      • 轴映射:3D 屏幕视图下,+x=右、+y=上、+z=前(看向屏幕外);世界场景下,+x=东、+z=北,+y 仍为上。

      • 不影响的部分:所有向量代数恒等式(点积对称性、叉积反交换律等)在任何手性下都成立;差异仅出现在"应用到具体旋转 / 投影"的最后一步。

      3D 坐标系组合总数

      2D 笛卡尔只有 8 种轴向组合(图 1.7),都可旋转对齐;3D 笛卡尔有 48 种组合(24 左手 + 24 右手),其中异手性 不可 对齐——这是把 3D 视为"50% 更复杂"是不够的根因。

      When:阅读本书公式时,默认在左手系;如读者使用右手系引擎,在脑中加一次 z → -z 的镜像即可。

      Example:把本书的视图矩阵直接喂给 OpenGL(右手指南),会出现"深度反转 + 朝向镜像"的复合错误,常见修正是在投影矩阵中乘一个 (1, 1, -1, 1) 的对角缩放。

      2.6 数学预备:求和 / 区间 / 弧度 / 三角 (Math Refresher)

      What:本节给出后续章节默认掌握的数学速览——求和记法、区间记法、弧度与角度互换、三角函数与恒等式。

      Why:向量点积 / 叉积、矩阵乘法、傅里叶分析都基于这些记法。速览集中放在这里,后续章节直接使用。

      How

      核心记法与换算:

      • 求和记法:\(\sum_{i=1}^{n} a_i = a_1 + a_2 + \cdots + a_n\);连乘用 Π

      • 区间记法[a, b] 闭区间(含端点),(a, b) 开区间(不含端点),[a, b) 半开;无穷端按开区间处理,如 latexmath:[0, +\infty)

      • 弧度 ↔ 角度:\(1 \text{ rad} = (180/\pi)^\circ \approx 57.29578^\circ\),\(1^\circ = (\pi/180) \text{ rad} \approx 0.01745329 \text{ rad}\)。

      • 三角函数(单位圆定义):\(\cos\theta = x,\ \sin\theta = y\)(射线端点 (x, y))。

      • 毕达哥拉斯恒等式(式 1-1 之一):\(\sin^2\theta + \cos^2\theta = 1\),\(1 + \tan^2\theta = \sec^2\theta\),\(1 + \cot^2\theta = \csc^2\theta\)。

      • 和差恒等式(式 1-1 主体):

      \[\sin(a + b) = \sin a \cos b + \cos a \sin b \cos(a + b) = \cos a \cos b - \sin a \sin b\]

      When:所有后续章节直接使用以上记法;弧度在 C++ 中以 double 存储,三角函数 std::sin / std::cos / std::tan 接收弧度。

      Example:把 30° 喂给 C++ std::sin 会得到 0.5 之外的奇怪值;正确做法是 std::sin(30 * M_PI / 180),对应表 1.2 第一行非零值。

      三、关键图表

      视觉图表

      图 1-1
      Figure 1. 图 1-1:1 只死羊(自然数的隐喻起源)
      图 1-2
      Figure 2. 图 1-2:自然数的数轴
      图 1-3
      Figure 3. 图 1-3:整数数轴(含负数"幽灵羊")
      图 1-4
      Figure 4. 图 1-4:虚构城市 Cartesia 的街道地图
      图 1-5
      Figure 5. 图 1-5:标准 2D 笛卡尔坐标空间
      图 1-6
      Figure 6. 图 1-6:屏幕坐标空间(+y 朝下)
      图 1-7
      Figure 7. 图 1-7:2D 中 8 种可能的轴向组合
      图 1-8
      Figure 8. 图 1-8:用 2D 笛卡尔坐标定位点
      图 1-9
      Figure 9. 图 1-9:典型点的 2D 笛卡尔坐标示例
      图 1-10
      Figure 10. 图 1-10:3D 笛卡尔坐标空间示意
      图 1-11
      Figure 11. 图 1-11:在 3D 中定位点
      图 1-12
      Figure 12. 图 1-12:左手坐标系
      图 1-13
      Figure 13. 图 1-13:右手坐标系
      图 1-14
      Figure 14. 图 1-14:左手 / 右手定则定义"正向旋转"
      图 1-15
      Figure 15. 图 1-15:本书采用的左手坐标系约定
      图 1-16
      Figure 16. 图 1-16:弧度——单位圆上的弧长
      图 1-17
      Figure 17. 图 1-17:标准位置的角
      图 1-18
      Figure 18. 图 1-18:斜边 / 邻边 / 对边
      图 1-19
      Figure 19. 图 1-19:使用 (x, y) 坐标的一般三角解释
      图 1-20
      Figure 20. 图 1-20:毕达哥拉斯定理示意

      非可视化条目

      非可视化条目(表 / 算法)
      编号 内容摘要

      表 1.1

      绕卡迪尔轴正向旋转时,左手系顺时针 / 右手系逆时针;列出三轴 +x / +y / +z+y→+z→-y→-z→+y 等 12 条映射。

      表 1.2

      常用角度(0°、30°、45°、60°、90°、120°、135°、150°、180°、210°、225°、240°、270°、300°、315°、330°、360°)的弧度值及六个三角函数值。

      式 1-1

      和差恒等式族:sin(a±b)cos(a±b)tan(a+b) 展开式;毕达哥拉斯恒等式 sin²θ + cos²θ = 1 等。

      核心公式对照表

      核心公式对照表
      式号 公式

      式 1-1(毕达哥拉斯)

      \(\sin^2\theta + \cos^2\theta = 1,\quad 1 + \tan^2\theta = \sec^2\theta,\quad 1 + \cot^2\theta = \csc^2\theta\)

      式 1-1(和差)

      \(\sin(a + b) = \sin a \cos b + \cos a \sin b\)

      \(\cos(a + b) = \cos a \cos b - \sin a \sin b\)

      弧度-角度换算

      \(1 \text{ rad} = (180/\pi)^\circ\)

      \(1^\circ = (\pi/180) \text{ rad}\)

      四、思维导图

      mindmap
        root((第 1 章 笛卡尔坐标系))
          数系与精度
            自然数到实数
            C++位宽选择
            第一法则
          2D 笛卡尔空间
            原点与轴
            点的有符号距离
            8种2D方向皆等价
          3D 笛卡尔空间
            z轴与三平面
            点的3D定位
            2D直觉在3D失效
          手性
            左手系顺时针
            右手系逆时针
            翻转一轴切换手性
          本书惯例
            左手系
            xyz前右上
            地理x东z北
          数学预备
            求和与区间
            弧度与角度
            三角与毕达哥拉斯

      五、重点与易错点

      1. 第一法则是工程取舍:3D 图形默认用 float,不要在不必要时升级到 double;反之物理 / 累积运算上 float 漂移明显,需 double

      2. 2D 中所有坐标系都等价:任意两个 2D 笛卡尔坐标系可旋转 / 镜像对齐;屏幕坐标与数学坐标的差异仅是 y 取向,不是"另一个坐标系"。

      3. 3D 手性不可旋转对齐:左手系与右手系是 不可 通过旋转互化的两类;只能在 3D 中通过反转一个轴切换。

      4. 手指定则给出旋转正方向:左手系正方向顺时针、右手系逆时针——表 1.1 列了三轴的具体映射,是后续叉积 / 旋转矩阵正确性的判断依据。

      5. 本书左手系约定:+x=右、+y=上、+z=前;移植到 OpenGL 右手系时第一件事是投影矩阵的 z 翻转(乘 (1, 1, -1, 1) 对角矩阵或调整矩阵第三行符号)。

      6. 弧度 vs 角度:C++ std::sin / std::cos 默认输入是弧度;把 30° 直接喂进去会得到 ~0.988 这种看似合理但错误的值,正确做法是 30 * M_PI / 180

      7. 三角恒等式是后续推导工具:式 1-1 的和差展开在第 2 章向量点积 / 第 8 章欧拉角旋转推导中会被反复引用。

      8. (x, y) 的二义性:既可表示 2D 点,又可表示开区间 / 2D 向量——靠上下文区分;推荐在表达式中显式写 P = (2, 4)(点)或 v = (2, 4)(向量)。

      9. 3D 不是 2D 的 50% 增量:维度叠加带来的复杂度是非线性的,许多 2D 简单问题在 3D 中 未定义(如三角形顺逆时针在 3D 中依赖观察方向),这是后续章节反复回到 "降维到 2D" 思路的原因。

      10. 跨章衔接:第 2 章在 3D 笛卡尔之上引入向量(位置 / 位移 / 方向);第 7 章引入极坐标作为 2D / 3D 中"方向 + 长度"分离的另一选择;第 10 章把三角 / 弧度推广到 3D 几何(球坐标 / 弧长参数化)。