Files
AIC-Project/docs/superpowers/specs/2026-07-16-model-decimate-bake-design.md
T

99 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ModelTranslator 减面与烘焙工具设计
日期:2026-07-16
## 目标
`Tools/ModelTranslator` 新增两个 headless Blender 工具,与现有 `model_translator.py` 组成完整管线:
1. **model_decimate.py**:把 FBX 模型减面到指定三角面数,并重展一套不重叠 UV
2. **model_bake.py**:以高模+低模两个 FBX 为输入,在低模 UV 上烘焙法线贴图,并把 color / metallic / roughness / ao 一并分离输出
```
高模.fbx ──工具1──▶ <名>_low.fbx ──工具2──▶ out_bake/<名>/ (低模fbx + 5张贴图)
(高模.fbx ──┘) └──工具3(现有)──▶ Unity XPbr 资源
```
工具2 产物命名对齐 ModelTranslator 纯网格约定(`<前缀>_<token>.png`),可直接喂给 `model_translator.py`
## 架构与文件布局
沿用现有"系统 Python CLI 包装器 + headless Blender 内部脚本"模式:
```
Tools/ModelTranslator/
model_decimate.py # 工具1 CLI
bl_decimate.py # └ Blender 内部执行(blender -b --factory-startup --python
model_bake.py # 工具2 CLI
bl_bake.py # └ Blender 内部执行
```
- `find_blender`CLI 参数 > `BLENDER_EXE` > 默认 `D:\tools\blender-5.0.0-windows-x64\blender.exe` > PATH)与 `run_blender`(子进程 + stdout `MT_SUMMARY ` JSON 行协议)逻辑与 `model_translator.py` 一致
- 仅依赖系统 Python 标准库 + Blender 5.0
## 工具1model_decimate.py
**CLI**
```bash
python model_decimate.py src/well1500.fbx --tris 5000 [-o <dir>] [--blender exe]
```
**Blender 内流程(bl_decimate.py**
1. 导入 FBX,收集所有 mesh 对象;非 mesh 对象(骨骼/空物体等)忽略并打警告(本工具只针对静态物件)
2. 多 mesh 时 join 成单对象(目标面数按总量控制,也为工具2烘焙简化)
3. 全面三角化,统计当前三角面数 `cur`;若 `cur <= 目标` 直接跳过减面并打提示
4. Decimate modifiercollapse`ratio = target/cur`apply 后再三角化统计;collapse 结果是近似值,误差 >3% 时按比例修正再来一轮,最多 2 轮修正
5. Smart UV Project 重展(angle_limit 66°,island_margin 按 2048 图约 4px),删除全部旧 UV 层
6. 材质槽原样保留(烘焙后无用,但不破坏信息)
7. 导出 `<原名>_low.fbx`;默认输出到源文件同目录,`-o` 可改
## 工具2model_bake.py
**CLI**
```bash
python model_bake.py <高模.fbx> <低模.fbx> [-o out_bake] [--size 2048] \
[--ray-distance N] [--samples 64] [--blender exe]
```
**Blender 内流程(bl_bake.py**
1. 分别导入高模、低模,各自 join 成单对象;校验低模有 UV 层,没有则报错退出(提示先跑工具1)
2. 射线距离(max ray distance / cage extrusion):默认取低模包围盒对角线的 2%,`--ray-distance` 覆盖(单位=场景单位)
3. 低模挂临时烘焙材质,内含烘焙目标 image 节点;渲染器 Cycles、CPU
4. 烘焙顺序(先烘依赖原始高模材质的 pass,再改节点图):
-`NORMAL` pass:切线空间,基于低模新 UV;高模材质的法线贴图输入保持原样,法线细节一并烘入
-`AO` passsamples 默认 64`--samples` 可调)
- ③ 逐通道 EMIT trick:把高模各材质 Principled BSDF 的 Base Color / Metallic / Roughness 输入(贴图连线或常量值)改接 Emission → 烘 `EMIT`,依次输出 color / metallic / roughness(每张 1 sample
- 所有 pass margin 16pxselected-to-active(高模 selected,低模 active
5. 颜色空间(吸取 well10k 双重 sRGB 编码教训,见 c682ab4):
- color 烘焙目标图建为 **sRGB**
- normal / metallic / roughness / ao 建为 **Non-Color**
- PNG 落盘后 Unity 端 sRGB 开关由工具3 生成的 `.meta` 控制
6. 输出到 `out_bake/<低模名去掉 _low 后缀>/`
- 低模 FBX(导出时 path_mode 剥离贴图路径)
- `<名>_color.png``<名>_normal.png``<名>_metallic.png``<名>_roughness.png``<名>_ao.png`
## 方案取舍记录
- **烘焙核心选 Cycles selected-to-active + EMIT trick**Cycles 无 metallic pass`DIFFUSE` pass 受光照/颜色空间干扰;把数据通道接 Emission 烘 `EMIT` 是标准做法,color/metallic/roughness 三张统一路径。headless 一次性会话,改节点图无需还原
- 否决"法线烘焙+原贴图搬运":低模重展新 UV 后与高模 UV 无对应关系,搬运不成立
- 否决手写 BVH raycast 采样:插值/抗锯齿/切线空间全要自己做,工作量大、质量难保证
- 减面用 Decimate modifiercollapse):Quadriflow remesh 只适合有机体且慢,不做
## 错误处理与局限
- 低模无 UV → 报错退出
- 高模某通道无贴图 → Principled 常量值接 Emission 照常烘,日志标注 `(常量)`
- 高低模位置/缩放需在同一坐标系(工具不做对齐);烘焙前打印两者包围盒尺寸,差异超 10% 打警告
- 法线按 OpenGL(+Y) 约定,不提供绿通道翻转
- 不支持骨骼/动画/多 UV 层;多 mesh 一律 join
## 测试
- `python -m unittest`:ratio 修正计算、射线距离估算、输出命名等纯逻辑函数的单元测试
- 冒烟测试:用 `src/well1500.fbx` 跑全管线——工具1 降到 5000 面 → 工具2 烘焙 → 工具3 转 Unity 资源;检查 5 张 PNG 存在且尺寸正确、低模 FBX 面数达标(±3%)
- 最终 Unity 手动验证(与 ModelTranslator 既往验证方式一致)