Files
AIC-Project/Tools/ModelTranslator/README.md
T
2026-07-23 15:09:24 +08:00

78 lines
8.1 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
用 headless Blender 把带 PBR 贴图的 FBX 转换为 **XPbr shader**`Test/XPbr`)可用的资源:
- 纯模型 FBX(剥离全部贴图,保留材质名/槽位)
- 每材质一套贴图(≤2048×2048):
- **基础贴图** `<模型>_<材质>_base.png`RGB=颜色,A=透明或 AO
- **混合贴图** `<模型>_<材质>_mix.png`:RG=球面编码法线,B=金属度,A=粗糙度
- Unity 开箱即用:`.mat`(已挂 XPbr、已连贴图)与全部 `.meta`(含 sRGB 设置、FBX 材质重映射)都预生成
## 依赖
- Blender 5.0(默认路径 `D:\tools\blender-5.0.0-windows-x64\blender.exe`;也可用 `--blender` 参数或环境变量 `BLENDER_EXE` 指定)
- UVPackmaster 4(可选,UV 排布质量更好:Blender 扩展 `uvpackmaster4` + 独立引擎,引擎路径经注册表自动发现;已装则 Blender 展开路径(seam/smart)的排布自动启用,未装自动回退内置 pack_islands
- 系统 Python 3.x(标准库 + Pillow——仅 `model_decimate.py` 绘 UV 观察图用;`pip install Pillow`
## 用法
```bash
cd Tools/ModelTranslator
python model_translator.py src/tong.fbx # 单文件
python model_translator.py src/ # 目录批量(*.fbx
python model_translator.py src/tong.fbx -o out --max-size 2048 --blender "D:\...\blender.exe"
```
输出到 `out/<模型名>/`
```
out/tong/
tong.fbx (+.meta) # 纯模型,材质槽已重映射到下面的 .mat
tong_Material_base.png (+.meta) # sRGB 开
tong_Material_mix.png (+.meta) # sRGB 关(线性数据,勿改)
tong_Material.mat (+.meta) # Test/XPbr
```
**把整个 `out/<模型名>/` 文件夹拷进 `Client/Assets/` 任意位置即可**,模型拖进场景直接生效。重复转换会复用已有 `.meta` 里的 GUID,不会破坏 Unity 引用。
## 减面与高低模烘焙(可选前置工具)
高面数模型先减面、再把细节烘到低模贴图,产物直接作为上面转换器的输入:
```bash
cd Tools/ModelTranslator
python model_decimate.py src/well1500.fbx --tris 5000 # -> src/well1500_low.fbx
python model_bake.py src/well1500.fbx src/well1500_low.fbx # -> out_bake/well1500/
python model_translator.py out_bake/well1500/well1500.fbx # -> out/well1500/Unity 资源)
```
- **model_decimate.py**:多 mesh 自动 join;**减面前清理网格**(按局部包围盒对角线相对焊接重合点 + 去退化面,给后端更干净的流形、减少被迫加的 seam);按 `--reducer` 后端减到 `--tris`(默认 Quad Remesher,失败自动回退 Decimate collapsecollapse 后端为 ±3%,最多 2 轮修正);旧 UV 全删后重展——默认锐边 seam 整岛展开(SLIM 展开后 `minimize_stretch` 松弛 + `average_islands_scale` 纹素均衡),质量门不达标(翻转 >2% 或重叠 >8%)先按更低 seam 角度扫描(55/45/35°)取过门且岛数最少者抢救,全失败才回退 Smart UV Project`--unwrap smart` 可直接选投影式展开;**`--max-overlap 0.15` 放宽重叠门限**,让更高 seam 角度(岛更少)能过门被选中——岛数优先、可接受略高重叠时用(翻转门限始终严格);排布默认用 UVPackmaster 4 重排(只在最终选定 UV 上跑一次,旋转步进调细到 15° 以利薄斜条对齐提升利用率;UVPM 启发式搜索在 headless 下会随机崩溃引擎故未启用),UVPM4 不可用自动沿用内置 pack_islands 布局;输出 `<名>_low.fbx``-o` 改目录)与 `<名>_low_uv.png`(UV 线框观察图,便于人工查阅切分/排布/碎岛——Blender 抽 UV 几何,系统 Python 用 Pillow 绘制,因 headless 无 GPU 无法用 Blender 直接出 PNG),日志报 UV 岛数/利用率与实际生效的 seam 角度
- **`--reducer collapse|quad`**(默认 `quad`):减面后端。`quad`**Quad Remesher** 出规整四边拓扑(针对 collapse 的碎三角/UV 展开难痛点),headless 下**直接调 `Engine/xremesh.exe` 引擎子进程**(导出选中 mesh → 写 RetopoSettings.txt → 阻塞轮询 progress.txt → 导回 retopo.fbx),**绕开插件的 modal 操作符**modal 在 `blender -b` 后台不执行,直接调操作符必然失败)。面数按 `--tris ÷ 2` 换算为目标四边形数,用 `ExactQuadCount=1` 尊重目标数(自适应模式在高细节硬表面模型上会把面数炸开数倍并连带 UV 重叠爆炸,故禁用);输出为近似面数(约 ±20%)。**任何失败——引擎缺失/超时/引擎报错/无有效输出/导回失败——都记警告并自动回退 collapse**,摘要 `reducer` 字段标 `quad->collapse`,绝不中断。**升级流程**:quad 后端先把高密度输入**预 collapse 到中等密度**`--qr-input-cap`,默认 50000——高密度网格直接 QR 必破洞),再 QR,导回后 `fill_holes` 补掉薄部位小洞,最后**软水密门**(补洞后仍比输入多出超容忍的破损才判灾难性、回退 collapse)。quad 成功时**保留四边、不三角化**导出(FBX/烘焙/Unity 均支持四边;这修掉了旧版 quad 被三角化的问题)。`QR_ENGINE` 环境变量可覆盖引擎路径(**权威**:显式设了就以它为准,无效即视同缺失走回退)。QR 输出为近似面数(约 ±20%,四边口径 `--tris÷2`);实测有机角色可保四边(如 100 万面 supergirl → 约 5000 四边、开边≤3),硬表面直边仍会被 QR 波动化(那类模型用 collapse)
- **model_bake.py**Cycles selected-to-active 烘焙。normal(切线空间 OpenGL +Y/ao 直接烘;color/metallic/roughness 把高模 Principled 对应输入接 Emission 烘 EMIT。`--size` 默认 2048`--samples` AO 采样默认 64,射线距离默认低模包围盒对角线 2%(`--ray-distance` 覆盖);低模无 UV 会报错,高低模包围盒差超 10% 打警告;导入后自动应用物体变换——未应用缩放的 FBX(如 cm 单位导出的 scale=0.01)会把射线距离缩到近零导致大面积烘空(脏色);固定 `-t 1` 单线程跑 Blender——5.0 的 selected-to-active 射线求交多线程有竞争,会随机 EXCEPTION_ACCESS_VIOLATION 崩溃
- 输出命名 `<名>_color/normal/metallic/roughness/ao.png`,正好命中转换器的纯网格贴图命名约定
## 转换规则
- 贴图识别:沿材质 Principled BSDF 连线找 Base Color / Alpha / Normal / Metallic / Roughness;内嵌与外置贴图(FBX 旁的松散文件)均支持
- AO 按贴图名匹配(含 `ao`/`occlusion`/`ambient`):先找材质内引用的贴图;FBX 未引用时自动搜索 FBX 同目录的图片文件,多候选优先与颜色贴图同前缀(`xxx_color.png``xxx_ao.png`
- **纯网格 FBX**(无材质或材质无贴图,常见于烘焙工具导出):自动以模型名新建材质,并按命名约定从 FBX 同目录识别整套贴图——`<前缀>_<token>.png`token 支持 `color/basecolor/albedo/diffuse``normal/nrm``metallic/metalness/metal``roughness/rough``ao/occlusion/ambient``alpha/opacity`;多套前缀时取与模型同名的一组
- 基础贴图 A 通道自动判定:**透明贴图 > 颜色贴图自带 alpha > AO 贴图 > 填白(255)**;判定为透明时 `.mat` 自动勾选 `Alpha As Transparency`AlphaTest 裁剪)
- 无对应贴图的通道用 Principled 常量值填充(会在日志中标注 `(常量)`
- 目标尺寸 = min(2048, 源贴图最大边),所有贴图缩放到统一尺寸
- 法线编码:`enc = n.xy / sqrt(2*(1+n.z)) * 0.5 + 0.5`,与 `XPbr_Base.hlsl``DecodeSphereMap` 配对
## 局限
- 材质必须是贴图直连 Principled BSDF 的标准 PBR;程序纹理/复杂混合节点无法识别(会打警告并退化为常量)
- 法线按 OpenGL 约定(+Y 向上)处理,不提供绿通道翻转
- 不做多材质图集合并/UV 重排;每材质一套贴图
- 动画/骨骼随 FBX 原样导出,不做处理
- 外置贴图文件丢失时打警告并退化为常量,不中断转换
## 开发
```bash
python -m unittest tests.test_unity_assets # Unity 模板/GUID 测试
"<blender>" -b --factory-startup --python tests/bl_test_encode.py # 法线编码 round-trip
```