Add ModelTranslator tool design spec

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ud18010
2026-07-15 10:43:01 +08:00
co-authored by Claude Opus 4.8
parent c29c6f5bac
commit 609788fe00
@@ -0,0 +1,89 @@
# ModelTranslator 工具设计文档
日期:2026-07-15
状态:已确认
## 目标
`Tools/ModelTranslator/` 下的 Python 工具:用 headless Blender 把带 PBR 贴图的 FBX(如 `src/tong.fbx`)转换为:
1. **纯模型 FBX**(剥离贴图,保留材质名/槽位)
2. **XPbr shader 所需贴图**(每材质一套,≤2048×2048):
- 基础贴图:RGB=颜色,A=透明 > AO > 255(自动判定)
- 混合贴图:RG=球面编码法线,B=金属度,A=粗糙度
3. **Unity 开箱即用资产**:贴图/材质/FBX 的 `.meta``.mat` 全部预生成,拷入 `Client/Assets/` 即可直接使用
## 环境
- Blender`D:\tools\blender-5.0.0-windows-x64\blender.exe`5.0),查找顺序:`--blender` 参数 → 环境变量 `BLENDER_EXE` → 上述默认路径 → PATH
- 外层 CLI 用系统 Python 3.12;图像处理在 Blender 内用 bpy + 自带 numpy,不引第三方依赖
## 文件结构
```
Tools/ModelTranslator/
model_translator.py # CLI 入口:找 blender、组命令行、汇报结果
bl_convert.py # Blender 内运行的转换脚本
README.md # 用法说明
src/ # 源 FBX(已存在)
out/<模型名>/ # 输出(git 忽略)
```
## CLI
```
python model_translator.py src/tong.fbx # 单文件
python model_translator.py src/ # 目录批量(*.fbx
[-o out] [--max-size 2048] [--blender <exe>]
```
## bl_convert.py 流程(每个 FBX
1. 空场景导入 FBX,解包全部内嵌贴图
2. 逐材质找 Principled BSDF,沿连线识别贴图:Base Color、Alpha、Normal(穿过 Normal Map 节点)、Metallic、RoughnessAO 按贴图名匹配(含 `ao`/`occlusion`/`ambient`,不区分大小写)
3. 目标尺寸 = min(max-size, 各源贴图最大边),所有参与贴图缩放到统一尺寸(`image.scale()`
4. 基础贴图:RGB=颜色贴图(无则 Principled 常量色);A=透明贴图 > AO 贴图 > 255
5. 混合贴图:
- RG=法线球面编码:切线法线 `n = rgb*2-1` 归一化后 `enc = n.xy/√(2(1+n.z)) × 0.5 + 0.5`;无法线贴图填 (0.5, 0.5)
- B=金属度贴图(取 R 通道)或 Principled 常量
- A=粗糙度贴图(取 R 通道)或 Principled 常量
6. 保存 RGBA PNG 到 `out/<模型名>/`
7. 删除材质中所有贴图节点,`path_mode='NONE'` 导出纯模型 FBX
8. 打印 JSON 摘要(stdout 标记行),runner 转为可读日志
## Unity 资产生成(model_translator.py 内完成,纯文本模板)
每材质:
| 文件 | 要点 |
|---|---|
| `<模型>_<材质>_base.png.meta` | TextureImportersRGB 开,maxTextureSize 2048 |
| `<模型>_<材质>_mix.png.meta` | TextureImporter**sRGB 关**(线性),maxTextureSize 2048 |
| `<模型>_<材质>.mat` | shader 引用 XPbr GUID(见下);`_MainTex`/`_MixTex` 引用预分配贴图 GUID;透明模式时写 keyword `_ALPHATEST_ON``_AlphaTest=1``_Metallic`/`_Roughness`/`_AO`=1.0 |
| `<模型>_<材质>.mat.meta` | NativeFormatImportermainObjectFileID 2100000 |
- XPbr shader GUID`cab897163f45445fa34263d6670bfc9e``Client/Assets/Game/shader/XShader/XPbr.shader.meta`,若该 meta 变更需同步工具常量)
- 模型 FBX 生成 `.meta`ModelImporter):`externalObjects` 按材质名重映射到生成的 `.mat` GUID,模型拖进场景直接生效
- 所有 GUID 用 `uuid4().hex` 预分配;同一模型重复转换时**复用已存在 meta 里的 GUID**(避免拷入 Unity 后再次转换导致引用断裂)
## 配套 shader 修改
`Client/Assets/Game/shader/XShader/XPbr_Base.hlsl``DecodeSphereMap` 入口加 `encoded = encoded * 2 - 1;`:现编码只能表示 xy≥0 的法线(无符号 rg),重映射后可表示全半球。只影响 XPbr(无存量资源),不动 XTex。
## 错误处理
- 找不到 Blender → 明确报错并提示 `--blender`
- 材质无 Principled BSDF → 警告,用全常量兜底(灰色、平面法线、金属 0、粗糙 0.5)
- 贴图输入是程序纹理/复杂节点 → 警告,用该输入的默认常量
- Blender 退出码非 0 → runner 透传 stderr 摘要
## 不做(YAGNI
合并图集/UV 重排、Cycles 烘焙、法线绿通道翻转选项(README 说明现状)、动画/骨骼处理(FBX 原样导出)。
## 验证
1. 实跑 `src/tong.fbx``src/woodcar.fbx`
2. 输出文件齐全,贴图尺寸 ≤2048
3. 法线 round-trip 校验:按 shader 公式解码生成贴图的 RG,与源法线角度误差 < 2°
4. 拷入 Unity 工程验证材质/模型开箱可用(人工步骤)