2.网格划分底层原理

网格划分(Tessellation曲面细分)底层原理

先分清两个名词,工业CAD里很容易混淆:

  1. Tessellation(曲面离散/网格化):把B‑Rep的解析曲面(球面、NURBS曲面)切成三角面片,给渲染显示用,就是OCCT给VTK喂三角数据的这个过程,我们现在讲的就是这个。
  2. 有限元网格划分(FEM Mesh):仿真求解用,生成四面体/六面体,给力学仿真算应力,这是另外一套算法,不要和渲染网格搞混。

你问的:为什么有的地方密、有的地方疏,能不能调,调的标准是什么,代码凭什么知道切多细,全部围绕渲染曲面离散Tessellation来讲。

1. 代码凭什么决定在哪里切、切多细?

B‑Rep里面每一张面,都是数学方程描述(NURBS曲面、圆柱面、球面),没有自带三角形。 算法核心思想:用三角形去逼近真实曲面,控制「三角面片和真实曲面之间的最大误差」。

核心判定指标:弦高误差(Chord Height Tolerance,弦高公差)

  • 想象一段圆弧:用一条直线弦连接圆弧两个端点。圆弧和这条直线之间的最大距离,就叫弦高。
  • 弦高越大:直线离真实曲面偏差越大,肉眼看就会有明显棱角。
  • 算法规则:只要当前这片三角形,和原始曲面的弦高超过设定阈值,就必须继续切割;小于阈值,就停止切割。

举个直观例子:

  • 平面:平面本身就是平直。三角面片贴上去之后,弦高永远=0,不需要切很多,少数几个大三角就搞定,网格稀疏。

  • 曲率很大的圆角、曲面拐角:曲面弯得厉害。大三角贴上去弦高会超标,算法就会不断递归切小三角,网格变稠密。

    ✅这就是你看到现象的根源:曲率越高,网格越密;越平的面,网格越稀疏。

补充第二个约束:最大边长

光靠弦高还不够。比如一个巨大平缓的球面,整体曲率很小,弦高达标,但是单个三角会变得巨大,视图缩放之后观感很差。 所以算法一般是两套约束同时生效:

  1. 弦高公差(优先,控制曲面逼近误差)
  2. 三角面片最大边长(限制单个三角不能无限大) 只要任意一个条件触发,就继续细分。

2. 细分是怎么执行的(代码大致逻辑,递归思路)

以OCCT的BRepMesh_IncrementalMesh(OCCT做网格化的核心类)为例: 伪代码逻辑,方便理解:

输入:一张B‑Rep曲面,全局弦高公差max_chord_height,三角最大边长max_edge_len

函数subdivide(曲面,三角片):
    1.计算这个三角面片,到原始解析曲面的【弦高误差】
    2.计算三角三条边的长度
    3.如果 弦高 > 允许公差  OR 边长 >最大边长:
        将这个三角形切分成2个/4个更小三角形
        对每一个新的小三角,递归调用subdivide()
    4.否则:
        停止细分,保留这个三角,输出到网格

不是均匀切!不是把曲面死板切成N×N格子。是自适应细分:弯的地方切碎,平坦地方少切。这就是“疏密不一样”。

⚠️注意:NURBS曲面还有参数空间,算法很多时候是在曲面uv参数域做细分,再映射回三维空间坐标,不是直接在3D空间切。

3. 能不能人为调控?怎么调?

完全可以调控,OCCT、VTK都开放参数。 OCCT中核心的两个参数:

  1. LinearDeflection 线性偏差,就是弦高公差,最重要参数
  2. AngularDeflection角度偏差:相邻三角法线夹角阈值;两个三角法线偏差超过这个角度,强制细分。专门处理圆角曲面。

行为表现:

  • 把LinearDeflection调小:允许的最大误差更小,整体网格变密,三角数量暴涨,曲面光滑,内存、GPU负载上升。
  • 调大:三角少,速度快,但是圆角位置会出现明显“多边形棱角”。

工程坑:很多新人直接写死一个固定0.1的偏差。但是模型尺寸有大有小!一个1000mm的大零件和一个1mm小零件,同一个绝对公差,效果天差地别。 所以很多软件会使用相对偏差:公差 = 模型包围盒尺寸 × 比例系数,按模型大小自动缩放。

4. 调控标准:调到什么程度才算合适?

没有万能固定数值,分两类目标:可视化显示 vs 导出STL给3D打印/仿真

①目标:软件界面可视化(绝大多数工业软件场景)

目的:肉眼看不出棱角,同时三角数量不能爆炸,保证交互拖动不卡顿。

  1. 肉眼观察准则:正常视图下,人眼分辨不出曲面的锯齿棱角;把模型放大到局部细节,圆角也看不出多边形台阶。
  2. 代价约束:三角总数量不能过高。比如一个装配体,总三角超过几百万之后,拖拽旋转界面就会明显掉帧卡顿。

实践经验:不要追求数学上无限精确,人眼不可见的误差就是可以接受的误差。 如果误差小到人眼看不见,再继续加密网格只会白白消耗性能,没有收益。

②目标:导出STL用于3D打印 /仿真

需要更高网格精度,公差要结合实际物理尺寸。 比如打印0.05mm精度的零件,你的弦高公差就要远小于打印精度,不然打印出来圆角是多边形。

反面两种坏情况

  1. 公差太小:三角爆炸。一个普通零件直接生成上千万三角,内存暴涨,VTK渲染卡顿,鼠标拖拽延迟。
  2. 公差太大:圆角曲面变成多边形棱角,视觉失真;导出STL做仿真,几何形状失真,后续仿真结果出错。

5.重要的现实局限

  1. 自适应细分是每一张B‑Rep面独立运算 两个相邻面,一个平面、一个圆角面,各自细分,会出现:两个面交界处,两边三角顶点无法完全对齐。 👉于是就会出现:网格缝隙。

    注意:这是网格层面的缝隙,不是底层B‑Rep拓扑缝隙。原始B‑Rep拓扑是完好的,仅仅网格化之后两套三角顶点没有对上。渲染时会出现一闪一闪的黑线,Z‑fighting闪烁。工业软件经常遇到这个bug。

  2. 自适应细分只针对渲染网格,不会修改底层B‑Rep。 调大/调小细分参数,只改变输出三角,原始曲面方程纹丝不动。

6.串联回你整条技术链路

B‑Rep精确曲面(OCCT CPU)
     ↓ 传入:弦高公差、角度公差、最大边长
自适应细分Tessellation(递归判断弦高误差,弯处密、平处疏)
     ↓输出疏密不等的三角面片
VTK接收网格 → OpenGL → GPU渲染

7.补充一个容易混淆点

前面讲的是OCCT的BRepMesh,B‑Rep曲面离散成三角用于显示。 有限元仿真软件的网格划分(ANSYS之类)是另一套算法:不仅考虑曲率,还要考虑应力梯度,应力集中区域网格进一步加密,输出四面体/六面体单元,用来数值求解,不是给显卡看的。不要把两者混在一起。

posted @ 2026-08-24 16:11  Drunker•L  阅读(33)  评论(0)    收藏  举报