日期:2025年4月13日标签:Computer Graphics

CAD 中的 Tessellation:从 BRep 曲面到 Triangle Mesh #

1. 什么是 Tessellation #

在 CAD 和计算机图形学中,Tessellation 通常可以翻译为:

  • 细分;
  • 镶嵌;
  • 曲面离散化;
  • 三角网格化。

在 CAD 渲染场景中,更容易理解的说法是:

Tessellation 是将 CAD 中的精确几何表示离散成 Triangle Mesh 的过程。

例如 CAD Kernel 中可能存在一个精确的圆柱面:

BRep Face
   ↓
Cylinder Surface

但是 WebGL/GPU 并不能直接绘制 Cylinder SurfaceNURBS SurfaceB-Spline Surface

GPU 最终绘制的通常是:

position buffer
normal buffer
index buffer
      ↓
Triangle Mesh
      ↓
WebGL

因此 CAD 模型真正进入渲染系统之前,一般需要经过:

BRep
 ↓
Tessellation
 ↓
Triangle Mesh
 ↓
WebGL / GPU

这里需要特别注意:

BRep 是精确几何模型,而 Triangle Mesh 通常只是 BRep 的近似渲染表示。

例如 Boolean、Fillet、Offset 等几何运算通常还是针对 BRep 执行,而不是针对渲染 Mesh 执行。


2. Tessellation 和 Triangulation 的区别 #

Tessellation 经常和 Triangulation(三角化 / 三角剖分) 混在一起使用。

在 CAD 场景下可以简单理解为:

Tessellation
    ↓
决定在哪里采样
    ↓
得到离散点和边界
    ↓
Triangulation
    ↓
连接成 Triangle

Triangulation 更关注:

已经有了一组二维点和边界以后,怎么把这个区域划分成三角形。

而 Tessellation 还需要解决:

为了用 Mesh 足够准确地逼近原来的精确曲面,应该在哪里生成采样点?生成多少采样点?

因此:

Triangulation 可以看作 Tessellation 过程中的一个核心步骤。

对于 CAD Face,可以把整个过程理解为:

精确 BRep Face
      ↓
确定边界
      ↓
几何采样
      ↓
Triangulation
      ↓
Triangle Mesh

3. 为什么 Tessellation 的对象是 Face,而不是整个无限 Surface #

BRep 中一个重要概念是:

Face 不等于 Surface。

例如一个 Plane Surface 理论上可以是无限大的:

────────────────────────
────────────────────────
────────────────────────
────────────────────────

但一个 BRep Face 可能只使用其中一小块:

       ┌──────────────┐
       │              │
       │     Face     │
       │              │
       └──────────────┘

因此不能简单地:

Surface
   ↓
全部三角化

而应该根据 Face 的拓扑边界决定有效区域:

Face
├── Surface
├── Outer Wire
└── Inner Wires

Tessellation 最终只应该覆盖:

Outer Wire 内部,并且排除所有 Inner Wire 表示的孔洞区域。


4. Face 有孔时应该如何三角化 #

例如下面这个 Face:

┌─────────────────────────┐
│                         │
│       ┌─────────┐       │
│       │  Hole   │       │
│       └─────────┘       │
│                         │
└─────────────────────────┘

其中:

外矩形 → Outer Wire
内矩形 → Inner Wire

如果只是随意在 Face 上采样一些点,再执行普通三角化:

采样点
  ↓
Triangulation

三角形可能跨过 Hole。

因此 CAD Face 的三角化通常需要把:

Outer Wire
Inner Wire

作为约束边界

也就是说:

三角形不能跨越 BRep Edge,Inner Wire 内部也不能产生三角形。

这类问题属于 Constrained Triangulation(约束三角剖分)


5. 为什么经常在 Surface 的 UV 空间中进行三角化 #

参数曲面可以写成:

[ P=S(u,v) ]

其中:

u、v

是 Surface 参数。

例如一个圆柱在三维空间中看起来是:

       _______
     /       \
    /         \
   |           |
   |           |
   |           |
    \         /

但它具有二维 UV 参数空间:

v
↑
│
│   ┌──────────────────┐
│   │                  │
│   │                  │
│   │                  │
│   └──────────────────┘
│
└────────────────────────→ u

BRep Face 的 Edge 又通常可以拥有对应 Surface 上的 P-Curve

因此可以形成这样一个过程:

BRep Face
   │
   ├── Surface
   │
   └── Wire / Edge
           ↓
        P-Curve
           ↓
      UV 参数空间
           ↓
Outer / Inner Boundary
           ↓
二维约束三角化
           ↓
      UV Triangles
           ↓
         S(u,v)
           ↓
      3D Triangles

例如二维三角形的三个顶点:

(u1, v1)
(u2, v2)
(u3, v3)

通过 Surface 求值得到:

[ P_1=S(u_1,v_1) ]

[ P_2=S(u_2,v_2) ]

[ P_3=S(u_3,v_3) ]

最终得到 GPU 可以绘制的三维 Triangle。


6. 为什么不能对曲面均匀采样 #

对于平坦区域:

────────────────────────

使用比较大的 Triangle 就已经能很好地逼近真实 Surface。

但如果曲率很大:

          ____
       __/    \__
    __/          \__

如果 Triangle 仍然很大:

●────────────────●
 \              /
   \            /
      ●────────

Mesh 和真实曲面之间就可能出现明显偏差。

因此实际 Tessellation 往往采用:

Adaptive Tessellation,自适应细分。

基本原则是:

平坦区域
↓
少量采样
↓
较大 Triangle


高曲率区域
↓
增加采样
↓
较小 Triangle

从而在:

几何精度
   ↕
Triangle 数量
   ↕
GPU 性能

之间取得平衡。


7. Chordal Deviation:弦偏差 #

Chordal Deviation 可以翻译为:

弦偏差、弦高误差

在一些 CAD Kernel 中也经常看到类似:

Linear Deflection,线性偏差。

它主要用于控制:

离散 Mesh 与真实几何之间的位置误差。

以曲线为例:

            真实曲线
          *********
       ***    ↑    ***
     ●────────│────────●
              d
             弦

两个采样点之间最终使用线段近似。

真实曲线和线段之间的最大距离 d 就可以理解为弦偏差。

假设 Tessellation 参数要求:

Chordal Deviation <= 0.1 mm

如果:

当前误差 = 0.5 mm

那么说明当前离散结果太粗:

继续增加采样点
      ↓
进一步细分

直到满足误差要求。

因此:

Chordal Deviation 越小
        ↓
要求越严格
        ↓
采样越密
        ↓
Triangle 越多
        ↓
Mesh 越接近真实 Surface

反之:

Chordal Deviation 越大
        ↓
允许误差越大
        ↓
Triangle 越少
        ↓
渲染性能越高

8. Angular Deviation:角偏差 #

Angular Deviation 通常翻译为:

角偏差。

它主要用于控制:

Surface 方向或者法向变化是否被 Mesh 足够准确地表达。

例如曲面不同位置的法向:

N1 ↑

        ↗ N2

                 → N3

如果一个 Triangle 覆盖整个区域:

●────────────●
 \          /
   \       /
      ●

虽然位置误差可能没有超过 Chordal Deviation,但真实 Surface 的方向变化可能已经非常明显。

因此还可以检查:

[ \theta = \angle(N_1,N_2) ]

如果:

θ > AngularDeviation

就继续进行细分。

可以简单记:

Chordal Deviation
        ↓
控制位置误差
        ↓
Mesh 离真实几何有多远


Angular Deviation
        ↓
控制方向误差
        ↓
曲面的弯曲变化是否表达充分

Chordal Deviation 和 Angular Deviation 都可以作为:

决定 Tessellation 采样密度和是否继续细分的误差判据。


9. 为什么相邻 Face 不能完全独立 Tessellation #

假设两个 BRep Face:

Face A
   │
   │ Shared Edge E
   │
Face B

它们共享同一条拓扑 Edge。

如果 Face A 自己对 Edge 采样:

●────●────●────●

而 Face B 自己重新采样:

●──●──────●──●─●

那么最终两个 Face 的 Mesh 边界:

Face A

────●────●────●────


Face B

──●──────●──●──────

顶点无法对应。

这样可能出现:

Crack / Seam,即 Mesh 裂缝。


10. 公共 Edge 应该统一离散 #

比较合理的设计是:

BRep Shared Edge
        ↓
统一进行 Curve Tessellation
        ↓
P0 P1 P2 P3 P4
        │
    ┌───┴───┐
    ↓       ↓
 Face A   Face B

两个 Face 的 Triangle Mesh 都必须使用:

P0
P1
P2
P3
P4

作为公共边界。

即:

Face A
────●────●────●────

Face B
────●────●────●────

这体现了一个非常重要的 CAD 思想:

Tessellation 不能完全脱离 BRep Topology 单独处理 Surface。

Topology 已经告诉我们:

Face A
Face B

共享:

Edge E

那么 Mesh 层也应该保持这层共享关系,从而保证模型 watertight,避免视觉裂缝。


11. Tessellation 最终产生什么数据 #

经过 Tessellation 后,一个 Face 最终可能得到:

struct FaceMesh {
    std::vector<Vec3> positions;
    std::vector<Vec3> normals;

    std::vector<Vec2> uvs;

    std::vector<uint32_t> indices;

    FaceId faceId;
};

然后上传到 WebGL:

positions
normals
uv
indices
   ↓
BufferGeometry
   ↓
GPU

对于 CAD 系统,还应该尽量保留:

Triangle
   ↓
FaceId

这样的对应关系。

因为 Picking 后:

Mouse
 ↓
Ray
 ↓
Triangle
 ↓
FaceId
 ↓
BRep Face

才能从渲染 Mesh 找回真正的 CAD 拓扑对象。


12. Tessellation 与 Picking 的关系 #

CAD 的 Triangle Mesh 虽然主要用于渲染,但也经常参与 Picking。

例如:

BRep Face
    ↓
Tessellation
    ↓
Triangles
    ↓
BVH

用户点击模型:

Mouse
 ↓
Ray
 ↓
BVH
 ↓
Triangle
 ↓
FaceId
 ↓
BRep Face

因此 Tessellation 不仅需要生成 Triangle,还最好保留:

Triangle → Face
Face → Entity

映射。

这也是 CAD Render Model 和普通 Three.js 场景之间一个很重要的区别。


13. 什么是 LOD #

LOD 是:

Level of Detail,细节层次。

核心思想是:

同一个 CAD 几何准备多个不同精细程度的 Mesh,根据当前观察距离或者屏幕尺寸选择不同版本。

例如:

BRep
 │
 ├── LOD 0
 │    100,000 triangles
 │
 ├── LOD 1
 │     20,000 triangles
 │
 └── LOD 2
       2,000 triangles

近距离观察:

Camera
  ↓

████████████
模型占据大量屏幕像素

→ LOD 0

远距离观察:

Camera
   ↓


                 ▪
                Model

→ LOD 2

因为模型在屏幕上可能只剩几十个像素,即使继续使用几十万个 Triangle,用户也无法看到区别。


14. LOD 和 Tessellation 的关系 #

LOD 本身不是 Tessellation 算法。

可以理解成:

LOD 是对多个不同 Tessellation 精度结果进行管理和选择的渲染策略。

例如:

                    BRep
                     │
       ┌─────────────┼─────────────┐
       ▼             ▼             ▼
精细 Tessellation  中等 Tessellation  粗 Tessellation
       │             │             │
       ▼             ▼             ▼
     LOD0          LOD1          LOD2

可以使用不同的 Chordal Deviation:

LOD0
Chordal Deviation = 0.01 mm

LOD1
Chordal Deviation = 0.1 mm

LOD2
Chordal Deviation = 1 mm

允许的几何误差越大:

Triangle 越少

15. Zoom 时是否应该重新 Tessellate #

如果用户只是:

Zoom In
Zoom Out
Rotate Camera

BRep 几何本身并没有改变。

因此通常不希望:

每次 Camera 改变
      ↓
重新 Tessellate BRep
      ↓
重新生成 Mesh
      ↓
重新上传 GPU

因为这一过程成本比较高。

一种更常见的设计是:

提前或者按需生成:

LOD0
LOD1
LOD2

      ↓

缓存

运行时:

Camera
 ↓
计算物体屏幕尺寸
 ↓
选择合适 LOD
 ↓
直接渲染已有 Mesh

这样 Camera 运动时只进行 Mesh 切换,而不是不断重新执行几何算法。


16. 为什么根据屏幕尺寸选择 LOD 比单纯根据距离更合理 #

例如两个零件:

Part A:10000 mm

Part B:10 mm

虽然它们离 Camera 的距离相同,但最终屏幕尺寸完全不同。

真正影响用户能否看到几何误差的是:

Mesh 的误差最终投影到屏幕后占多少像素。

因此大型 CAD 系统可以考虑:

Tessellation 几何误差
       ↓
Camera Projection
       ↓
Screen Space Error
       ↓
选择 LOD

例如:

当前误差投影到屏幕 < 0.5 px

→ 当前 LOD 已经足够

这样比简单判断:

distance < 100

更加合理。


17. Tessellation 应该属于哪个模块 #

从职责上看,Tessellation 更适合属于:

Geometry Kernel / Geometry Processing 层。

因为 Tessellation 需要理解:

BRep
Face
Edge
P-Curve
Surface
UV
Tolerance
Topology

这些都是 Geometry Kernel 的核心数据。

因此比较自然的架构是:

Geometry Kernel
      │
      │ BRep
      ↓
Tessellation
      │
      │ Triangle Mesh
      ↓
Render Engine
      │
      ↓
WebGL

Render Engine 不需要真正理解:

NURBS
B-Spline
TopoDS_Face
P-Curve

它主要消费:

Position
Normal
UV
Index
EntityId
FaceId

等渲染数据。


18. 云 CAD 中 Tessellation 可以放在哪里 #

云 CAD 中 Geometry Kernel 不一定只存在于某一个地方。

服务端 Tessellation #

架构:

Server

BRep
 ↓
Geometry Kernel
 ↓
Tessellation
 ↓
Triangle Mesh
 ↓
Network
 ↓
Browser
 ↓
WebGL

优点:

  • 浏览器 CPU 压力较小;
  • Kernel 统一;
  • 客户端不需要携带完整几何算法。

缺点:

  • Mesh 数据量可能比较大;
  • 编辑以后需要服务器往返;
  • 网络延迟会影响交互。

浏览器 WASM Tessellation #

例如把 C++ Geometry Kernel 编译成 WASM:

Browser

BRep
 ↓
WASM Geometry Kernel
 ↓
Tessellation
 ↓
Triangle Mesh
 ↓
WebGL

优点:

  • 局部几何修改后可以直接重新 Tessellate;
  • 减少服务器往返;
  • 交互响应速度更好。

缺点:

  • 浏览器 CPU 和内存压力增加;
  • Kernel/WASM 包可能较大;
  • 大型几何算法在浏览器端成本较高。

服务端 + 浏览器混合 #

实际云 CAD 可以采用混合方案:

首次打开大型模型
      ↓
Server 直接提供已有 Mesh
      ↓
快速首屏


用户修改当前零件
      ↓
Browser WASM
      ↓
局部 Tessellation


复杂 Boolean / 几何计算
      ↓
Server Kernel

最终根据:

几何计算成本
网络传输量
首屏速度
交互延迟
客户端性能
缓存策略

决定任务放在哪里执行。


19. 一个完整的 CAD Tessellation 流程 #

最终可以把整个过程总结成:

                   BRep Face
                      │
          ┌───────────┴───────────┐
          ↓                       ↓
       Surface                 Topology
                                  │
                          Outer / Inner Wire
                                  │
                               Edge
                                  │
                              P-Curve
          │                       │
          └───────────┬───────────┘
                      ↓
                 UV 参数空间
                      │
                      ↓
              建立约束边界
                      │
                      ↓
          根据几何误差进行采样
                      │
         ┌────────────┴────────────┐
         ↓                         ↓
 Chordal Deviation          Angular Deviation
   控制位置误差               控制方向误差
         │                         │
         └────────────┬────────────┘
                      ↓
             Adaptive Tessellation
                      │
                      ↓
          Constrained Triangulation
                      │
                      ↓
               UV Triangles
                      │
                    S(u,v)
                      │
                      ↓
               3D Triangles
                      │
            ┌─────────┴─────────┐
            ↓                   ↓
        Position             Normal
            │                   │
            └─────────┬─────────┘
                      ↓
                 Index Buffer
                      │
                      ↓
                Triangle Mesh
                      │
                      ↓
                WebGL / GPU

20. 总结 #

CAD 中的 Tessellation 可以概括为:

将精确的 BRep 几何按照一定误差要求离散成 Triangle Mesh,使其能够被 GPU 实时绘制。

其中几个最重要的概念是:

BRep 边界 #

不能只对无限 Surface 三角化,而需要根据:

Outer Wire
Inner Wire

确定 Face 的真正有效区域。

UV 参数空间 #

可以利用:

Surface + P-Curve

把复杂三维曲面的边界转化到二维 UV 空间,在二维空间完成约束三角剖分,再映射回三维。

自适应 Tessellation #

不是所有区域采用同样密度:

平坦区域 → 少量 Triangle
高曲率区域 → 更多 Triangle

Chordal Deviation #

控制:

Mesh 与真实几何之间的位置误差。

Angular Deviation #

控制:

Mesh 对真实 Surface 方向变化的表达误差。

两者都是决定采样密度和是否继续细分的重要标准。

共享 Edge 一致性 #

两个相邻 BRep Face 的公共 Edge 应该统一离散,并共享相同边界采样点,从而避免:

Crack / Seam

LOD #

同一个 BRep 可以拥有多个不同 Tessellation 精度的 Mesh:

LOD0
LOD1
LOD2

根据屏幕尺寸或 Screen Space Error 选择适当版本,而不是用户每次 Zoom 都重新 Tessellate。

最终需要建立一个非常重要的认识:

BRep
↓
精确几何模型

Tessellation
↓
几何离散化

Triangle Mesh
↓
近似渲染表示

WebGL
↓
GPU 实时显示

对于同时涉及几何建模和 WebGL 渲染的 CAD 系统而言,Tessellation 正是连接 Geometry Kernel 和 Render Engine 的关键桥梁。

(完)

目录