1. 几何体基础:点、线、面、体的数学定义与计算机表示

各位同学好,咱们开始第一讲。说实话,很多做三维图形的朋友,一上来就怼着 Maya 或 Blender 的快捷键猛学,结果模型一复杂就崩,或者导出到引擎里破面严重。根子在哪儿?就是没搞懂最基础的四个概念:点、线、面、体。

我当年刚入行时也吃过这个亏。有一次做建筑可视化,一个曲面屋顶怎么调都像被踩过一脚,后来才发现是顶点数据精度丢了。嗯,从那以后,我每次建新项目都会先检查几何基元的底层表示。

1.1 数学定义:从抽象到具象

咱们先抛开计算机,用数学语言把这几样东西说清楚。

元素 数学定义 维度 典型表示
点 空间中位置,无大小、无方向 0D P = (x, y, z)
线 点的连续集合,有长度无宽度 1D L(t) = P₀ + t·V
面 线的连续扫描或边界围成,有面积无体积 2D 平面方程 Ax+By+Cz+D=0
体 面的封闭集合,有体积 3D 三角网格 / 体素 / B-Rep

你想想看,点是最纯粹的。它就是一个坐标,不占地方。线呢,是点沿着某个方向走出来的轨迹。面是线扫出来的,或者由一圈线围起来的。体就是面围起来的封闭空间。

核心概念:在计算机图形学里,我们几乎只用「点」来存储,「线、面、体」都是通过点之间的关系推导出来的。说白了,你硬盘里存的只有一堆 float 数组,剩下的全靠算法算。

1.2 计算机表示:内存里的几何

数学上说得再漂亮,到了计算机里都得变成数据结构。我个人习惯把常见的表示法分成三类:显式、隐式、过程式。

1.2.1 显式表示

最直接,也是游戏引擎和建模软件最常用的方式。

  • 点云:就是一堆点,没有连接关系。激光扫描出来的原始数据就是点云。
  • 多边形网格:最经典的是三角网格。每个三角形存三个顶点索引。
  • 细分曲面:从粗糙网格开始,通过细分规则生成光滑曲面。Pixar 的建模管线大量用这个。
// 一个简单的三角网格结构(C风格伪代码)
struct Mesh {
    float3* vertices;      // 顶点数组
    int*     indices;      // 索引数组,每3个int构成一个三角形
    int      vertexCount;
    int      indexCount;
};

我的经验:做实时渲染时,尽量用三角网格。四边面虽然建模时好用,但 GPU 光栅化只认三角形。我曾经把一个四边面模型直接丢给渲染管线,结果出现了诡异的裂缝——因为驱动自动三角化时把对角线连反了。

1.2.2 隐式表示

不直接存点,而是存一个函数。函数值为 0 的地方就是表面。

  • SDF(有符号距离场):每个点存一个到最近表面的距离,正负表示在内部还是外部。
  • 代数曲面:比如球体:x² + y² + z² - r² = 0。
  • B-Rep(边界表示):CAD 软件的核心,用面、环、边、点的拓扑关系描述实体。

注意:隐式表示做布尔运算(并、交、差)非常方便,但渲染时需要「提取等值面」,也就是 marching cubes 算法。这个算法如果网格分辨率不够,会丢失细节。我踩过这个坑——用 32³ 的体素提取一个薄壁零件,结果壁直接消失了。

1.2.3 过程式表示

不存几何数据,只存生成规则。比如分形、L-system、程序化生成。

  • 优点:内存占用极小,细节可以无限多。
  • 缺点:不能直接编辑,每次渲染都要重新计算。

1.3 知识结构图

下面这张图把本章的核心脉络串起来了。你可以把它当作一个思维导图来用。

几何体基础:知识体系 几何体基础 点 (0D) 线 (1D) 面 (2D) 体 (3D) 计算机表示法 显式表示 隐式表示 过程式表示 点云 三角网格 细分曲面 SDF 代数曲面 B-Rep 分形 L-system 程序化生成 选择哪种表示法,取决于你的应用场景:实时渲染用三角网格,CAD 用 B-Rep, 科学计算用 SDF,艺术创作用细分曲面或程序化生成。

1.4 不同表示法的对比

在实际项目中,选哪种表示法直接决定了你的开发成本和运行效率。我整理了一张对比表,你可以存下来当参考。

特性 三角网格 SDF B-Rep 细分曲面
存储大小 中等 大(体素分辨率决定) 小(只存边界) 小(存控制网格)
渲染速度 快(GPU 原生支持) 慢(需提取等值面) 慢(需离散化) 中等(需细分计算)
布尔运算 难(需网格布尔库) 容易(直接操作函数) 容易(拓扑操作) 难
编辑友好度 高(逐顶点编辑) 低(全局函数难局部调) 高(参数化编辑) 高(控制点编辑)
典型应用 游戏、影视、VR 物理仿真、碰撞检测 CAD、工业设计 角色建模、动画

一个小建议:如果你刚开始做几何相关的项目,先从三角网格入手。它最直观,调试也方便。等你把顶点、索引、法线这些东西玩熟了,再去碰 SDF 和 B-Rep 会轻松很多。

1.5 避坑指南

最后分享几个我踩过的坑,希望能帮你省点时间。

  • 顶点重复:同一个位置存了两个顶点,导致法线计算错误、焊接失败。解决方案:导入模型后先做一次顶点去重(weld vertices)。
  • 非流形几何:一条边被三个面共享,或者一个顶点被两个不连通的面共用。这在 3D 打印时会直接报错。检查工具:Blender 的「3D Print Toolbox」插件。
  • 坐标精度丢失:把 float 转成 half 或者 int 时,顶点位置偏移。尤其是大世界场景,远离原点的顶点精度会急剧下降。解决方案:使用局部坐标系或 double 精度。
  • 索引顺序错误:三角形顶点顺序不一致,有的顺时针有的逆时针,导致背面剔除出现闪烁。统一用右手定则,逆时针为正面。

我曾经犯过的错:有一次做地形 LOD,为了省内存把顶点坐标从 float 转成了 uint16。结果远处的地形像波浪一样抖动——因为精度不够,相邻 LOD 层的顶点位置对不上。从那以后,我所有涉及 LOD 的顶点数据都保留 float 精度,只在渲染时压缩。

好了,这一章的内容就到这里。点、线、面、体这四个概念虽然基础,但它们是整个三维世界的基石。后面的所有章节——从网格简化到布尔运算再到参数化建模——都建立在这些基础之上。希望你能把这些概念真正吃透,而不是背几个定义就完事。