From 9f4e02265cc36557d31150a19fb748f04f3a6446 Mon Sep 17 00:00:00 2001 From: ud18010 Date: Fri, 17 Jul 2026 17:26:16 +0800 Subject: [PATCH] =?UTF-8?q?ModelTranslator:=20bl=5Fuvgate=20UV=20=E8=B4=A8?= =?UTF-8?q?=E9=87=8F=E9=97=A8=E2=80=94=E2=80=94rizom=20=E4=BA=A7=E7=89=A9?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=EF=BC=8C=E6=97=A0=20UV/=E4=B8=8D=E8=BE=BE?= =?UTF-8?q?=E6=A0=87=E5=B0=B1=E5=9C=B0=20seam=20=E9=87=8D=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tools/ModelTranslator/bl_uvgate.py | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Tools/ModelTranslator/bl_uvgate.py diff --git a/Tools/ModelTranslator/bl_uvgate.py b/Tools/ModelTranslator/bl_uvgate.py new file mode 100644 index 00000000..92963415 --- /dev/null +++ b/Tools/ModelTranslator/bl_uvgate.py @@ -0,0 +1,57 @@ +"""Blender 内运行:校验低模 FBX 的 UV 质量门;无 UV 或不达标就地 seam 重展并覆盖导出。 +调用:blender -b --factory-startup --python bl_uvgate.py -- [mode_label] +mode_label 仅用于日志/回退警告中标注上游展开方式(默认 rizom)。""" +import os +import sys + +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + + +def main(): + import bpy + import json + from bl_decimate import (join_meshes, uv_gate_ok, _collect_uv_metrics, + _do_unwrap) + argv = sys.argv[sys.argv.index("--") + 1:] + fbx = argv[0] + mode_label = argv[1] if len(argv) > 1 else "rizom" + warnings = [] + + bpy.ops.wm.read_factory_settings(use_empty=True) + bpy.ops.import_scene.fbx(filepath=fbx) + meshes = [o for o in bpy.data.objects if o.type == 'MESH'] + if not meshes: + print("MT_SUMMARY " + json.dumps({"error": "FBX 中没有 mesh"}, + ensure_ascii=False)) + return + obj = join_meshes(meshes) + + if obj.data.uv_layers: + m = _collect_uv_metrics(obj) + if uv_gate_ok(m["flipped"], m["overlap"]): + m["mode"] = mode_label + print("MT_SUMMARY " + json.dumps( + {"uv": m, "reexported": False, "warnings": warnings}, + ensure_ascii=False)) + return + warnings.append("%s UV 质量不达标(翻转 %.1f%% 重叠 %s),回退 seam" + % (mode_label, m["flipped"] * 100, + "%.1f%%" % (m["overlap"] * 100) + if m["overlap"] is not None else "未知")) + else: + warnings.append("%s 输出无 UV,回退 seam" % mode_label) + + m = _do_unwrap(obj, "seam", warnings) # 内部自带 smart 回退 + if m["mode"] == "seam": + m["mode"] = "seam_fallback" + bpy.ops.object.select_all(action='DESELECT') + obj.select_set(True) + bpy.ops.export_scene.fbx(filepath=os.path.abspath(fbx), use_selection=True, + path_mode='STRIP', embed_textures=False) + print("MT_SUMMARY " + json.dumps( + {"uv": m, "reexported": True, "warnings": warnings}, + ensure_ascii=False)) + + +if __name__ == "__main__" and "--" in sys.argv: + main()