Initial commit: AIGame Unity client with URP, HybridCLR, YooAsset and tooling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-09-21 14:21:07 +08:00
co-authored by Cursor
commit f3f66ab063
931 changed files with 112366 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
"""FBX/GLB/glTF 减面 CLI:减到指定三角面数并重展 UV(seam 展开 + UVPM4 排布),输出 <名>_low.fbx。
用法:python model_decimate.py src/well1500.glb --tris 5000 [-o dir]
[--unwrap seam|smart] [--max-overlap 0.15] [--blender exe]"""
import argparse
import os
from bl_decimate import model_format
from mt_run import find_blender, run_blender_script
def main():
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("input", help="高模 FBX/GLB/glTF 文件")
ap.add_argument("--tris", type=int, required=True, help="目标三角面数")
ap.add_argument("-o", "--out", default=None, help="输出目录(默认源文件同目录)")
ap.add_argument("--unwrap", choices=("seam", "smart"), default="seam",
help="UV 展开:seam=锐边接缝整岛展开(默认),smart=Smart UV Project")
ap.add_argument("--max-overlap", type=float, default=None,
help="UV 重叠容忍上限(0-1,默认内置 0.08);调高可让更高 seam 角度过门、减少碎岛")
ap.add_argument("--blender", default=None)
args = ap.parse_args()
try:
model_format(args.input)
except ValueError as exc:
ap.error(str(exc))
if args.tris <= 0:
ap.error("--tris 必须为正整数")
if args.max_overlap is not None and not (0.0 < args.max_overlap <= 1.0):
ap.error("--max-overlap 必须在 (0, 1] 内")
blender = find_blender(args.blender)
name = os.path.splitext(os.path.basename(args.input))[0]
outdir = args.out or os.path.dirname(os.path.abspath(args.input))
out_fbx = os.path.join(outdir, name + "_low.fbx")
s = run_blender_script(blender, "bl_decimate.py",
[args.input, out_fbx, str(args.tris), args.unwrap,
"" if args.max_overlap is None else str(args.max_overlap)])
print("== %s: %d -> %d 面(目标 %d)-> %s" %
(s["src"], s["tris_before"], s["tris_after"], s["target"], out_fbx))
u = s["uv"]
overlap = "%.1f%%" % (u["overlap"] * 100) if u["overlap"] is not None else "n/a"
print(" UV: 模式=%s 岛数=%d 利用率=%.1f%% 翻转=%.1f%% 重叠=%s" %
(u["mode"], u["islands"], u["fill"] * 100, u["flipped"] * 100, overlap))
if s.get("uv_polys"):
try:
import json as _json
from uv_preview import render_uv_png
with open(s["uv_polys"], encoding="utf-8") as fp:
polys = _json.load(fp)
render_uv_png(polys, s["uv_preview"])
print(" UV 观察图: %s" % s["uv_preview"])
except Exception as e:
print(" [警告] UV 观察图渲染失败:%s" % e)
finally: # sidecar 是内部临时文件,无论渲染成败都清掉
if os.path.exists(s["uv_polys"]):
os.remove(s["uv_polys"])
for w in s["warnings"]:
print(" [警告] %s" % w)
if __name__ == "__main__":
main()