From 24084a667503bb5086dfafbec89fec89337e798f Mon Sep 17 00:00:00 2001 From: ud18010 Date: Fri, 17 Jul 2026 16:23:14 +0800 Subject: [PATCH] =?UTF-8?q?ModelTranslator:=20=E8=B4=A8=E9=87=8F=E9=97=A8?= =?UTF-8?q?=E6=8A=BD=E7=BA=AF=E5=87=BD=E6=95=B0=20uv=5Fgate=5Fok=20+=20?= =?UTF-8?q?=E5=87=8F=E9=9D=A2=20none=20=E6=A8=A1=E5=BC=8F=EF=BC=88rizom=20?= =?UTF-8?q?=E7=AE=A1=E7=BA=BF=E5=89=8D=E7=BD=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tools/ModelTranslator/bl_decimate.py | 18 ++++++++++++++---- .../ModelTranslator/tests/test_bl_decimate.py | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Tools/ModelTranslator/bl_decimate.py b/Tools/ModelTranslator/bl_decimate.py index 11b8e753..21a309e0 100644 --- a/Tools/ModelTranslator/bl_decimate.py +++ b/Tools/ModelTranslator/bl_decimate.py @@ -1,5 +1,5 @@ """Blender 内运行:FBX 减面到指定三角面数 + UV 重展(锐边 seam 或 Smart UV Project)。 -调用:blender -b --factory-startup --python bl_decimate.py -- [seam|smart] +调用:blender -b --factory-startup --python bl_decimate.py -- [seam|smart|none] """ import os import sys @@ -28,6 +28,11 @@ UV_FLIP_TOL = 0.02 # 质量门:UV 翻转面占比超此值回退 smart_pr UV_OVERLAP_TOL = 0.08 # 质量门:UV 重叠面占比阈值(手工 UV 同口径约 5%,灾难性失败 >20%) +def uv_gate_ok(flipped, overlap): + """UV 质量门:翻转与重叠占比都在阈值内。overlap 为 None(op 不可用)按 0 处理。""" + return flipped <= UV_FLIP_TOL and (overlap or 0.0) <= UV_OVERLAP_TOL + + def count_islands(n_faces, adjacent_pairs): """union-find 数 UV 岛:n_faces 个面,adjacent_pairs 为 UV 连续的面索引对。""" parent = list(range(n_faces)) @@ -199,8 +204,7 @@ def _do_unwrap(obj, mode, warnings): if mode == "seam": _unwrap_seam(obj, warnings) m = _collect_uv_metrics(obj) - overlap = m["overlap"] or 0.0 - if m["flipped"] <= UV_FLIP_TOL and overlap <= UV_OVERLAP_TOL: + if uv_gate_ok(m["flipped"], m["overlap"]): m["mode"] = "seam" return m warnings.append("seam 展开质量不达标(翻转 %.1f%% 重叠 %s),回退 smart_project" @@ -250,7 +254,13 @@ def main(): if not within_tolerance(target, cur) and cur > target: warnings.append("修正 %d 轮后仍超差:%d 面(目标 %d ±3%%)" % (MAX_RETRY, cur, target)) - uv_info = _do_unwrap(obj, unwrap_mode, warnings) + if unwrap_mode == "none": + # rizom 管线:跳过展开,UV 由后续 RizomUV 步骤生成 + _clear_uv_layers(obj.data) + uv_info = {"mode": "none", "islands": 0, "fill": 0.0, + "flipped": 0.0, "overlap": None} + else: + uv_info = _do_unwrap(obj, unwrap_mode, warnings) out_dir = os.path.dirname(os.path.abspath(out_fbx)) os.makedirs(out_dir, exist_ok=True) # 仅导出合并后的对象;整场景导出会把 armature/empty 等非 mesh 带进 _low.fbx diff --git a/Tools/ModelTranslator/tests/test_bl_decimate.py b/Tools/ModelTranslator/tests/test_bl_decimate.py index 91269446..c73ca1bb 100644 --- a/Tools/ModelTranslator/tests/test_bl_decimate.py +++ b/Tools/ModelTranslator/tests/test_bl_decimate.py @@ -75,5 +75,22 @@ class TestFillRatio(unittest.TestCase): self.assertEqual(bd.fill_ratio([]), 0.0) +class TestUvGateOk(unittest.TestCase): + def test_clean_passes(self): + self.assertTrue(bd.uv_gate_ok(0.0, 0.0)) + + def test_boundary_passes(self): + self.assertTrue(bd.uv_gate_ok(bd.UV_FLIP_TOL, bd.UV_OVERLAP_TOL)) + + def test_flip_exceeds_fails(self): + self.assertFalse(bd.uv_gate_ok(0.03, 0.0)) + + def test_overlap_exceeds_fails(self): + self.assertFalse(bd.uv_gate_ok(0.0, 0.09)) + + def test_overlap_none_treated_as_zero(self): + self.assertTrue(bd.uv_gate_ok(0.01, None)) + + if __name__ == "__main__": unittest.main()