feat(asset-catalog): 简化分析工具+新增汇总和AI推理脚本
- analyze_meshes: 移除失败的 LineTrace 和六面分析,只保留基础属性 (包围盒、锚点、复杂度、Socket、材质槽位、自动Tag) - build_database: 新增离线汇总脚本,将 meshes/*.json 扁平化为 统一的 asset_database.json - ai_inference: 新增 GLM API 批量推理脚本,按类别分批推断语义信息 (朝向、表面高度、功能描述、交互属性、降级方案) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
"""资产数据库汇总脚本。
|
||||
|
||||
读取 asset-catalog 的扫描结果(meshes/*.json),汇总为统一的单文件
|
||||
asset_database.json,以资产名为 key 扁平化存储。
|
||||
|
||||
此脚本不依赖 UE5,可离线运行。
|
||||
|
||||
用法:
|
||||
python build_database.py [--input DIR] [--output FILE]
|
||||
|
||||
--input 扫描输出目录,默认 output/asset-catalog
|
||||
--output 输出文件路径,默认 <input>/asset_database.json
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
_SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
if str(_SCRIPT_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(_SCRIPT_DIR))
|
||||
|
||||
from _common import read_json, write_json, iso_now
|
||||
|
||||
TAG = "[BuildDB]"
|
||||
|
||||
|
||||
def build_database(input_dir: Path, output_file: Path) -> dict:
|
||||
"""汇总 meshes/*.json 为统一数据库。
|
||||
|
||||
Args:
|
||||
input_dir: 包含 meshes/ 子目录的扫描输出根目录
|
||||
output_file: 输出的 asset_database.json 路径
|
||||
|
||||
Returns:
|
||||
统计信息 dict
|
||||
"""
|
||||
meshes_dir = input_dir / "meshes"
|
||||
if not meshes_dir.exists():
|
||||
print(f"{TAG} 错误: {meshes_dir} 不存在,请先运行 analyze_meshes")
|
||||
return {"status": "error", "reason": "no meshes dir"}
|
||||
|
||||
# 收集所有子目录的扫描文件
|
||||
mesh_files = sorted(meshes_dir.glob("*.json"))
|
||||
if not mesh_files:
|
||||
print(f"{TAG} 错误: {meshes_dir} 下无 JSON 文件")
|
||||
return {"status": "error", "reason": "no mesh files"}
|
||||
|
||||
print(f"{TAG} 发现 {len(mesh_files)} 个扫描文件")
|
||||
|
||||
# 扁平化合并
|
||||
assets = {}
|
||||
total = 0
|
||||
skipped = 0
|
||||
|
||||
for mf in mesh_files:
|
||||
try:
|
||||
data = read_json(mf)
|
||||
except Exception as e:
|
||||
print(f"{TAG} 警告: 读取 {mf.name} 失败: {e}")
|
||||
continue
|
||||
|
||||
subfolder = data.get("subfolder", mf.stem)
|
||||
meshes = data.get("meshes", {})
|
||||
if not meshes:
|
||||
continue
|
||||
|
||||
for name, mesh_data in meshes.items():
|
||||
total += 1
|
||||
|
||||
# 跳过无包围盒的(加载失败的)
|
||||
if mesh_data.get("bounding_box") is None:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
# 构建统一条目
|
||||
entry = {
|
||||
"ue_path": mesh_data.get("ue_path", ""),
|
||||
"subfolder": subfolder,
|
||||
"bounding_box": mesh_data.get("bounding_box"),
|
||||
"pivot": mesh_data.get("pivot"),
|
||||
"mesh_complexity": mesh_data.get("mesh_complexity", {}),
|
||||
"material_slots": mesh_data.get("material_slots", []),
|
||||
"sockets": mesh_data.get("sockets", []),
|
||||
"tags": {
|
||||
"style": mesh_data.get("style_tags", []),
|
||||
"scene": mesh_data.get("scene_tags", []),
|
||||
},
|
||||
"ai_inference": None,
|
||||
}
|
||||
|
||||
# 如果资产名重复(不同子目录下同名),加后缀
|
||||
key = name
|
||||
if key in assets:
|
||||
safe_sub = subfolder.replace("/", "_").replace("\\", "_")
|
||||
key = f"{name}_{safe_sub}"
|
||||
print(f"{TAG} 注意: 资产名重复 {name},使用 {key}")
|
||||
|
||||
assets[key] = entry
|
||||
|
||||
# 写入数据库
|
||||
db = {
|
||||
"metadata": {
|
||||
"generated_at": iso_now(),
|
||||
"source": "asset_catalog_v1",
|
||||
"total_assets": len(assets),
|
||||
"skipped_no_bbox": skipped,
|
||||
"input_files": [mf.name for mf in mesh_files],
|
||||
},
|
||||
"assets": assets,
|
||||
}
|
||||
|
||||
write_json(db, output_file)
|
||||
print(f"{TAG} ✅ 汇总完成: {len(assets)} 个资产 → {output_file}")
|
||||
print(f"{TAG} 跳过 {skipped} 个无包围盒资产 / 总计 {total}")
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
"total": total,
|
||||
"assets": len(assets),
|
||||
"skipped": skipped,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="汇总资产扫描数据为统一 JSON 数据库")
|
||||
parser.add_argument(
|
||||
"--input", type=str,
|
||||
default=str(_SCRIPT_DIR.parent.parent / "output" / "asset-catalog"),
|
||||
help="扫描输出目录 (默认: output/asset-catalog)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output", type=str, default=None,
|
||||
help="输出文件路径 (默认: <input>/asset_database.json)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
input_dir = Path(args.input)
|
||||
output_file = Path(args.output) if args.output else input_dir / "asset_database.json"
|
||||
|
||||
result = build_database(input_dir, output_file)
|
||||
if result.get("status") != "ok":
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user