"""高低模烘焙 CLI:在低模 UV 上烘出 normal/ao/color/metallic/roughness 五张贴图。 产物命名对齐 model_translator.py 纯网格约定,可直接作为其输入。 用法:python model_bake.py <高模.fbx> <低模.fbx> [-o out_bake] [--size 2048] [--ray-distance N] [--samples 64] [--blender exe]""" import argparse import os from bl_bake import output_stem from mt_run import HERE, find_blender, run_blender_script def main(): ap = argparse.ArgumentParser(description=__doc__) ap.add_argument("high", help="高模 FBX(带材质/贴图)") ap.add_argument("low", help="低模 FBX(须有 UV,见 model_decimate.py)") ap.add_argument("-o", "--out", default=os.path.join(HERE, "out_bake")) ap.add_argument("--size", type=int, default=2048, help="烘焙贴图边长") ap.add_argument("--ray-distance", type=float, default=None, help="射线距离(场景单位),默认低模包围盒对角线 2%%") ap.add_argument("--samples", type=int, default=64, help="AO 采样数") ap.add_argument("--blender", default=None) args = ap.parse_args() blender = find_blender(args.blender) stem = output_stem(os.path.splitext(os.path.basename(args.low))[0]) outdir = os.path.join(args.out, stem) ray = "auto" if args.ray_distance is None else str(args.ray_distance) # -t 1:Blender 5.0 的 selected-to-active 烘焙射线求交是多线程的(cast_ray_highpoly # / TBB parallel_for),存在竞争会随机 EXCEPTION_ACCESS_VIOLATION 崩溃;单线程稳定 s = run_blender_script(blender, "bl_bake.py", [args.high, args.low, outdir, str(args.size), ray, str(args.samples)], blender_args=("-t", "1")) print("== %s(高 %d 面 / 低 %d 面,射线距离 %.4f)-> %s" % (s["stem"], s["high_tris"], s["low_tris"], s["ray_distance"], outdir)) for name, fname in s["outputs"].items(): print(" %-10s %s" % (name, fname)) for w in s["warnings"]: print(" [警告] %s" % w) if __name__ == "__main__": main()