9.VTK拾取的原理
VTK拾取(Pick)原理:鼠标点屏幕,怎么定位到三维零件
先把场景建立起来: 屏幕是2D像素,鼠标拿到的只是 (x,y) 屏幕坐标。但是模型是三维空间里的B‑rep转出来的三角面片,存在世界三维坐标。拾取本质就是:2D屏幕坐标反向推导三维物体上的交点。
注意:VTK拾取操作全部是在CPU完成计算,GPU不参与拾取计算,GPU只管画图。
VTK提供好几套拾取器,工业软件最常用两个:
vtkCellPicker:单元拾取,拾取三角面片(精度最高,工业场景首选)vtkPointPicker:点拾取,只拾取顶点
还有一个vtkWorldPointPicker,性能快但是精度差,很少用在CAD。
核心底层思路:射线拾取(Ray Casting)
鼠标点击屏幕某一个像素点(sx, sy)。
- 反投影:把2D屏幕点,反向生成一条三维射线 相机有投影矩阵、视图矩阵。VTK做矩阵逆运算: 从相机镜头位置出发,穿过鼠标点击的屏幕像素,向三维场景深处发射一条无限长射线。
通俗比喻:拿激光枪,从摄像机位置,对准鼠标点击的屏幕那个点,向三维场景开枪。这条激光就是拾取射线。
- 遍历场景里所有Actor(零件) 场景里面每一个零件,对应一个
vtkActor,每个Actor背后是vtkPolyData(一堆三角面片)。 拿这条射线,依次和这个Actor内部每一个三角面片做射线‑三角形求交数学计算。 - 求交结果
- 如果射线和某个三角形相交:记录交点三维坐标、是哪个Actor(哪个零件)、是哪个三角单元cell id、交点距离相机的距离。
- 如果多个面片都和射线相交:取离相机最近的那一个交点,就是鼠标点到的物体。
- 返回拾取结果: 得到:点击到哪个零件Actor、三角单元ID、三维交点坐标、法向量等信息。
为什么工业CAD里,vtkCellPicker是首选?
vtkCellPicker就是完整做射线与每个三角形求交。 ✅优点:精度高,点面片任意位置都可以命中,不是只能点顶点。 ❌缺点:模型三角数量巨大的时候,速度会慢。 比如大型装配体,几十万个三角面片,每点一次鼠标,CPU就要循环几十万三角形做求交运算,会卡顿。
痛点来了:大型装配直接用CellPicker直接遍历全部三角,性能爆炸。工业软件会做很多优化。
常见优化手段(真实工业软件会这么干)
1. 空间加速树(BVH包围盒树)
不会傻傻遍历全部三角形。 每个Actor、每个部件维护包围盒,先拿拾取射线和包围盒做快速碰撞检测。
-
如果射线连包围盒都碰不到:直接跳过这个零件,内部所有三角直接跳过,不用算三角形求交。
-
只有包围盒相交,才进去遍历内部三角面片。
VTK新版本自带BVH加速,老版本需要自己构建。
2. 层级过滤
装配体很多零件隐藏、半透明,拾取的时候直接跳过隐藏Actor。
3. 硬件拾取(GPU拾取,VTK也支持)
另一条完全不同路线:颜色拾取(OpenGL拾取) 原理: 渲染的时候,给场景中每一个零件分配独一无二的颜色ID。 后台渲染一张离屏帧缓冲纹理(不显示给用户看),每个零件用专属ID颜色绘制。 鼠标点击(sx,sy),去这张后台贴图读取该像素的颜色,颜色直接映射到零件ID。
✅优点:速度极快,海量模型也很快,计算交给GPU。 ❌缺点:
- 会占用GPU显存;
- 只能拿到Actor,很难拿到精确面片交点、法向量;
- 透明、混合渲染场景容易出错。
很多大型CAD软件两种拾取混用:
- 普通选择零件:GPU颜色拾取,追求速度
- 需要测量、打点、剖切,需要精确交点:切回CPU射线拾取
vtkCellPicker拿精确三维交点。
非常重要的坑,和我们前面的知识串起来
VTK拾取,操作对象是三角面片网格PolyData,它完全不知道B‑rep!
举个例子: STEP文件导入,OCCT的B‑rep立方体,网格化输出12个三角形给VTK。 你鼠标拾取得到的是:命中第5号三角单元。 VTK不知道这个三角属于B‑rep的哪一张面Face、哪一条边Edge。
👉这就是工业软件开发的经典鸿沟:
- VTK拾取返回:
Actor + cellId(网格层面信息) - 业务需要:“我点到了模型的哪个B‑rep面、哪条边”
你自己要做映射表:网格化的时候,记录【三角单元ID ↔ OCCT的Face/Edge】的对应关系保存下来。拾取拿到cellId之后,查表反向找到原始B‑rep拓扑。
很多新手踩坑:VTK拾取完,只拿到面片,拿不到原始CAD拓扑,无法做倒角、删除面这类建模操作。根源就在这里。
完整流程串起来(结合整套链路)
- STEP → OCCT解析得到B‑rep
- OCCT网格化,B‑rep的每一张Face输出若干三角面片;建立映射表:三角ID → 原始Face
- 三角PolyData喂给VTK,渲染窗口显示模型
- 用户鼠标点击屏幕,得到2D像素坐标
- VTK生成拾取射线,遍历Actor,做射线三角求交,得到命中cellId
- 拿着cellId去查表,反向找到原始OCCT B‑rep的Face
- 上层业务就可以执行:高亮这个面、删除面、测量、倒角等操作。
补充几个常见现象解释
- 鼠标点上去选不中模型
- 射线求交容差设置太小;
- 网格化质量差,面片法线反向;
- Actor没有加入渲染场景。
- 明明点A零件,却选中背后B零件 没有取距离相机最近交点;或者面片法线翻转。
- 大装配拾取卡顿 没有开启BVH加速,CPU暴力遍历全部三角面片。
简单对比两种拾取
| 拾取方式 | 实现 | 计算位置 | 优势 | 短板 |
|---|---|---|---|---|
| CellPicker射线拾取 | 射线与三角形求交 | CPU | 交点精确,可以拿到面片信息 | 大模型慢,需要BVH加速 |
| GPU颜色拾取 | 离屏渲染ID颜色 | GPU | 速度极快 | 拿不到精细交点,透明容易出错 |

浙公网安备 33010602011771号