"""诊断:导入 FBX 检查几何是否损坏(NaN 顶点/退化面/validate 修复量)。 用法:blender -b --factory-startup --python tests/bl_diag_mesh.py -- [apply] """ import math import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) def main(): import bpy from bl_decimate import join_meshes argv = sys.argv[sys.argv.index("--") + 1:] path = argv[0] do_apply = len(argv) > 1 and argv[1] == "apply" bpy.ops.wm.read_factory_settings(use_empty=True) before = set(bpy.data.objects) bpy.ops.import_scene.fbx(filepath=path) new = [o for o in bpy.data.objects if o not in before] meshes = [o for o in new if o.type == 'MESH'] print("DIAG objects=%d meshes=%d" % (len(new), len(meshes))) for o in new: print("DIAG obj=%r type=%s scale=%s" % (o.name, o.type, tuple(round(s, 4) for s in o.scale))) obj = join_meshes(meshes) if do_apply: bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) bpy.context.view_layer.objects.active = obj bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) print("DIAG transform applied") me = obj.data print("DIAG verts=%d polys=%d dims=%s" % ( len(me.vertices), len(me.polygons), tuple(round(d, 4) for d in obj.dimensions))) nan_verts = 0 huge_verts = 0 for v in me.vertices: x, y, z = v.co if any(math.isnan(c) or math.isinf(c) for c in (x, y, z)): nan_verts += 1 elif max(abs(x), abs(y), abs(z)) > 1e6: huge_verts += 1 print("DIAG nan_verts=%d huge_verts=%d" % (nan_verts, huge_verts)) zero_area = sum(1 for p in me.polygons if p.area < 1e-12) print("DIAG zero_area_polys=%d" % zero_area) # validate(verbose) 会打印它修的每个问题;返回 True 表示有改动 changed = me.validate(verbose=True) print("DIAG validate_changed=%s" % changed) print("DIAG after_validate verts=%d polys=%d" % (len(me.vertices), len(me.polygons))) print("DIAG DONE") if __name__ == "__main__" and "--" in sys.argv: main()