From ffde55bf9af789b752fc2855de6ccd40df8c06ad Mon Sep 17 00:00:00 2001 From: ud18010 Date: Thu, 16 Jul 2026 10:23:13 +0800 Subject: [PATCH] =?UTF-8?q?ModelTranslator:=20=E5=87=8F=E9=9D=A2+=E9=AB=98?= =?UTF-8?q?=E4=BD=8E=E6=A8=A1=E7=83=98=E7=84=99=E5=B7=A5=E5=85=B7=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- .../2026-07-16-model-decimate-bake-design.md | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-16-model-decimate-bake-design.md diff --git a/docs/superpowers/specs/2026-07-16-model-decimate-bake-design.md b/docs/superpowers/specs/2026-07-16-model-decimate-bake-design.md new file mode 100644 index 00000000..27c42509 --- /dev/null +++ b/docs/superpowers/specs/2026-07-16-model-decimate-bake-design.md @@ -0,0 +1,98 @@ +# 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 纯网格约定(`<前缀>_.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 + +## 工具1:model_decimate.py + +**CLI**: + +```bash +python model_decimate.py src/well1500.fbx --tris 5000 [-o ] [--blender exe] +``` + +**Blender 内流程(bl_decimate.py)**: + +1. 导入 FBX,收集所有 mesh 对象;非 mesh 对象(骨骼/空物体等)忽略并打警告(本工具只针对静态物件) +2. 多 mesh 时 join 成单对象(目标面数按总量控制,也为工具2烘焙简化) +3. 全面三角化,统计当前三角面数 `cur`;若 `cur <= 目标` 直接跳过减面并打提示 +4. Decimate modifier(collapse)`ratio = target/cur`,apply 后再三角化统计;collapse 结果是近似值,误差 >3% 时按比例修正再来一轮,最多 2 轮修正 +5. Smart UV Project 重展(angle_limit 66°,island_margin 按 2048 图约 4px),删除全部旧 UV 层 +6. 材质槽原样保留(烘焙后无用,但不破坏信息) +7. 导出 `<原名>_low.fbx`;默认输出到源文件同目录,`-o` 可改 + +## 工具2:model_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` pass:samples 默认 64(`--samples` 可调) + - ③ 逐通道 EMIT trick:把高模各材质 Principled BSDF 的 Base Color / Metallic / Roughness 输入(贴图连线或常量值)改接 Emission → 烘 `EMIT`,依次输出 color / metallic / roughness(每张 1 sample) + - 所有 pass margin 16px,selected-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 modifier(collapse):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 既往验证方式一致)