"""Reads every exported FBX back into an empty scene and checks what is in it. Run: blender -b --python verify_fbx.py""" import bpy, os, glob, json from mathutils import Vector HERE = os.path.dirname(os.path.abspath(__file__)); FDIR = os.path.join(os.path.dirname(HERE), 'fbx') rep = json.load(open(os.path.join(HERE, 'build_report.json'))); out = {}; bad = [] for path in sorted(glob.glob(os.path.join(FDIR, '*.fbx')) + glob.glob(os.path.join(FDIR, 'modules', '*.fbx'))): bpy.ops.wm.read_factory_settings(use_empty=True) bpy.ops.import_scene.fbx(filepath=path) arms = [o for o in bpy.data.objects if o.type == 'ARMATURE']; meshes = [o for o in bpy.data.objects if o.type == 'MESH'] name = os.path.relpath(path, FDIR) if len(arms) != 1: bad.append((name, 'armatures', len(arms))); continue a = arms[0]; roots = [b.name for b in a.data.bones if b.parent is None] lo = Vector((1e9,) * 3); hi = Vector((-1e9,) * 3); unw = 0; tris = 0 for m in meshes: for v in m.data.vertices: p = m.matrix_world @ v.co for k in range(3): lo[k] = min(lo[k], p[k]); hi[k] = max(hi[k], p[k]) if not v.groups: unw += 1 m.data.calc_loop_triangles(); tris += len(m.data.loop_triangles) want = rep['audit'].get(m.name) if want and want['tri_count'] != len(m.data.loop_triangles): bad.append((name, m.name, 'tris', want['tri_count'], len(m.data.loop_triangles))) if not any(md.type == 'ARMATURE' for md in m.modifiers): bad.append((name, m.name, 'no armature modifier')) if not m.data.uv_layers: bad.append((name, m.name, 'no uv')) if roots != ['root']: bad.append((name, 'roots', roots)) if len(a.data.bones) != rep['bones']: bad.append((name, 'bones', len(a.data.bones))) if unw: bad.append((name, 'unweighted verts', unw)) out[name] = dict(bones=len(a.data.bones), meshes=len(meshes), tris=tris, size_m=[round(hi[k] - lo[k], 3) for k in range(3)], lowest_z=round(lo.z, 4), armature_scale=round(a.scale.x, 4), materials=sorted({s.material.name for m in meshes for s in m.material_slots if s.material})) json.dump(dict(files=out, problems=bad), open(os.path.join(HERE, 'fbx_report.json'), 'w'), indent=1) for k, v in out.items(): if os.sep not in k and '/' not in k: print('FBX', k, v['bones'], 'bones', v['meshes'], 'meshes', v['tris'], 'tris', 'size', v['size_m'], 'minz', v['lowest_z'], 'armscale', v['armature_scale']) print('FBX FILES', len(out), 'PROBLEMS', len(bad), bad[:10])