系列文章目录
- 【3D AICG 系列-1】Trellis v1 和 Trellis v2 的区别和改进
- 【3D AICG 系列-2】Trellis 2 的O-voxel (上) Shape: Flexible Dual Grid
- 【3D AICG 系列-3】Trellis 2 的O-voxel (下) Material: Volumetric Surface Attributes
- 【3D AICG 系列-4】Trellis 2 的Shape SLAT Flow Matching DiT 训练流程
- 【3D AICG 系列-5】Trellis 2 的 Pipeline 推理流程的各个中间结果和形状
- 【3D AICG 系列-6】OmniPart 训练流程梳理
- 【3D AICG 系列-7】PartUV 代码流程深度解析
文章目录
- 系列文章目录
- [PartUV 流程图详解](#PartUV 流程图详解)
-
- [1. 系统整体架构图](#1. 系统整体架构图)
- [2. 递归展开详细流程](#2. 递归展开详细流程)
- [3. 合并展开算法流程](#3. 合并展开算法流程)
- [4. 部件边界平滑流程](#4. 部件边界平滑流程)
- [5. 数据流图](#5. 数据流图)
- [6. 并行处理流程](#6. 并行处理流程)
- [7. 打包流程](#7. 打包流程)
- [8. 关键决策点](#8. 关键决策点)
- [9. 失真评估流程](#9. 失真评估流程)
- [10. 完整调用链](#10. 完整调用链)
PartUV 流程图详解
1. 系统整体架构图
输出层
打包层 (Python)
核心展开层 (C++)
预处理层 (Python)
输入层
是
否
3D网格文件
.obj/.glb
加载网格
修复网格
合并顶点/修复非2流形
PartField推理
生成层次树
保存预处理结果
加载层次树
递归处理树节点
提取子网格
尝试多种展开方法
评估失真
失真 < 阈值?
保存为部件
继续分割
选择打包方法
Blender打包
UVPackMaster打包
最终网格
带UV坐标
2. 递归展开详细流程
展开方法
失真 < 阈值
失真 >= 阈值
是
否
是
否
开始处理节点
提取节点对应的面
提取子网格 Vc, Fc
尝试多种展开方法
unwrap_aligning_merge
合并展开
unwrap_aligning_plane
平面对齐
unwrap_aligning_BB
包围盒对齐
unwrap_aligning_one
单面展开
评估失真和图表数
评估失真和图表数
评估失真和图表数
评估失真和图表数
选择最佳候选
检查失真
首次达到阈值?
必须分割
保存为部件
设置图表限制
图表限制 > 2?
尝试优化分割
获取左右子节点
平滑部件边界
递归处理左子树
递归处理右子树
合并左右结果
比较并选择最佳
获取左右子节点
平滑部件边界
递归处理左子树
递归处理右子树
合并左右结果
返回结果
结束
3. 合并展开算法流程
是
是
否
否
输入网格 V, F
计算面法向量
基于OBB对齐分割
初始部件
构建部件邻接图
按大小排序部件
还有可合并的部件?
选择最小部件
找到最佳合并目标
尝试合并
合并成功?
更新邻接图
跳过该部件
输出最终部件列表
对每个部件进行UV展开
计算失真
返回结果
4. 部件边界平滑流程
否
是
是
否
是
否
输入部件列表和面邻接关系
遍历所有面
当前面在部件边界?
获取相邻面
统计相邻面所属部件
至少2个邻居
属于同一其他部件?
重新分配该面
更新部件列表
还有边界面?
返回平滑后的部件
5. 数据流图
输出数据
展开数据
预处理数据
输入数据
网格文件
顶点 V: N×3
面 F: M×3
修复后的网格
部件树 Tree
节点记录 NodeRecord
子网格 Vc, Fc
部件列表 Components
UV坐标 UV: N×2
失真值 Distortion
UVParts
Component列表
最终网格 + UV
6. 并行处理流程
串行分支
并行分支
是
否
开始处理根节点
递归深度 < parallelDepth?
并行处理
串行处理
线程1: 处理左子树
线程2: 处理右子树
等待完成
合并结果
处理左子树
处理右子树
返回最终结果
7. 打包流程
blender
uvpackmaster
part-based
multi-atlas
展开完成
加载 final_components.obj
选择打包方法
使用 bpy 调用 Blender
使用 BlenderProc
加载网格
调用 Blender 打包API
保存 final_packed.obj
加载 UVPackMaster 插件
打包模式?
部件感知打包
同一部件的图表在一起
多图集打包
根据部件树分配
保存 final_packed.obj
输出最终结果
8. 关键决策点
是
否
否
是
否
是
是
否
是
否
是
否
处理节点
节点面数 <= 1?
单面展开
提取子网格
尝试展开
展开成功?
返回空结果
失真 < 阈值?
必须分割
首次达到阈值?
创建部件
设置图表限制
图表限制 > 2?
尝试优化分割
分割结果更好?
使用分割结果
递归分割
返回结果
9. 失真评估流程
渲染错误: Mermaid 渲染失败: Parse error on line 7: ... F --> G[失真 = max(3D/2D, 2D/3D)] -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'
10. 完整调用链
main()
└─> partuv_pipeline()
├─> preprocess()
│ ├─> load_mesh_and_merge()
│ ├─> fix_mesh_trimesh()
│ └─> PF_pipeline()
│ └─> PFInferenceModel.process_face()
│
├─> pipeline_numpy() / pipeline()
│ └─> pipeline() [C++]
│ ├─> load_mesh_with_validation()
│ ├─> Tree() [加载部件树]
│ ├─> computeFaceAdjacency()
│ └─> pipeline_helper() [递归]
│ ├─> ExtractSubmesh()
│ ├─> get_uv_wrapper()
│ │ └─> get_uv()
│ │ └─> unwrap_aligning_merge()
│ │ ├─> prepareOBBData()
│ │ ├─> merge_components()
│ │ └─> unwrap_component()
│ │
│ ├─> get_best_part()
│ ├─> compare_new_parts()
│ └─> smoothComponentEdge()
│
└─> save_results()
└─> pack_mesh() [可选]
├─> pack_with_blender()
└─> pack_with_uvpackmaster()
这些流程图帮助理解 PartUV 的完整工作流程和关键决策点。