From 1b8656270d18d3d638455492a36dcb328c972d5f Mon Sep 17 00:00:00 2001 From: ud18010 Date: Tue, 21 Jul 2026 11:41:25 +0800 Subject: [PATCH] =?UTF-8?q?ModelTranslator:=20bl=5Fdecimate=20=E6=8A=BD?= =?UTF-8?q?=E5=8F=96=20UV=20=E5=87=A0=E4=BD=95=E5=88=B0=20sidecar=20JSON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- Tools/ModelTranslator/bl_decimate.py | 32 +++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/Tools/ModelTranslator/bl_decimate.py b/Tools/ModelTranslator/bl_decimate.py index 0a9864ed..25b2f3c0 100644 --- a/Tools/ModelTranslator/bl_decimate.py +++ b/Tools/ModelTranslator/bl_decimate.py @@ -326,6 +326,21 @@ def _do_unwrap(obj, mode, warnings): return m +def _collect_uv_polygons(obj): + """提取每个面的 UV 多边形(归一化坐标):[[[u,v], ...], ...],供外部 PIL 绘图。 + 无 UV 层返回空列表。""" + import bmesh + bm = bmesh.new() + bm.from_mesh(obj.data) + uv = bm.loops.layers.uv.active + polys = [] + if uv is not None: + for f in bm.faces: + polys.append([[l[uv].uv.x, l[uv].uv.y] for l in f.loops]) + bm.free() + return polys + + def main(): import bpy import json @@ -364,6 +379,17 @@ def main(): warnings.append("修正 %d 轮后仍超差:%d 面(目标 %d ±3%%)" % (MAX_RETRY, cur, target)) uv_info = _do_unwrap(obj, unwrap_mode, warnings) + uv_png = os.path.splitext(os.path.abspath(out_fbx))[0] + "_uv.png" + uv_polys_json = os.path.splitext(os.path.abspath(out_fbx))[0] + "_uv.polys.json" + uv_preview = None + try: + polys = _collect_uv_polygons(obj) + os.makedirs(os.path.dirname(uv_polys_json), exist_ok=True) + with open(uv_polys_json, "w", encoding="utf-8") as fp: + json.dump(polys, fp) + uv_preview = uv_png # 目标 PNG;实际绘制由 model_decimate(系统 Python + PIL)完成 + except Exception as e: + warnings.append("UV 几何导出失败(%s),跳过观察图" % e) out_dir = os.path.dirname(os.path.abspath(out_fbx)) os.makedirs(out_dir, exist_ok=True) # 仅导出合并后的对象;整场景导出会把 armature/empty 等非 mesh 带进 _low.fbx @@ -373,7 +399,11 @@ def main(): print("MT_SUMMARY " + json.dumps( {"src": os.path.basename(src), "fbx": os.path.basename(out_fbx), "tris_before": orig, "tris_after": cur, "target": target, - "uv": uv_info, "warnings": warnings}, ensure_ascii=False)) + "uv": uv_info, + "uv_preview": uv_preview, + "uv_polys": uv_polys_json if uv_preview else None, + "warnings": warnings}, + ensure_ascii=False)) if __name__ == "__main__" and "--" in sys.argv: