fix(level-builder): 锚点补偿+旋转修复+天空盒+解析器去重
- asset_mapping: 38种BSP资产实测锚点+pivot_offset_xy自动补偿 - scene_builder: Rotator改关键字参数修正旋转轴映射 - scene_builder: spawn前XY锚点补偿(支持Yaw旋转) - scene_builder: 新增ExponentialHeightFog+大气效果后处理 - build_cmdline: 构建后自动添加雾+GameMode+DirectionalLight大气 - build_guide_parser: 去重+全局地面+旋转列名兼容+边界段范围修正 - BarrierWall实际尺寸修正(60×210非20×100) - 搭建指南: 全局地面中心坐标+西边界旋转统一+院门改双开门
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
"""BSP 资产锚点检测脚本。
|
||||
|
||||
在 UE5 编辑器 Python 环境中运行,检测每个资产的 Bounds Origin,
|
||||
判断锚点是中心、角落还是底部中心。
|
||||
|
||||
用法:
|
||||
方式1 — 命令行: python main.py check-pivots
|
||||
方式2 — 编辑器内: exec(open(r"check_pivots.py").read())
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# 将 level-builder 根目录加入 sys.path
|
||||
_SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
_LB_DIR = _SCRIPT_DIR
|
||||
if str(_LB_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(_LB_DIR))
|
||||
|
||||
from config.asset_mapping import MESH_ASSETS
|
||||
|
||||
try:
|
||||
import unreal
|
||||
HAS_UNREAL = True
|
||||
except ImportError:
|
||||
HAS_UNREAL = False
|
||||
|
||||
|
||||
def check_pivots():
|
||||
"""检测所有 BSP 资产的锚点类型。"""
|
||||
if not HAS_UNREAL:
|
||||
print("[错误] 需要在 UE5 编辑器 Python 环境中运行")
|
||||
return
|
||||
|
||||
results = []
|
||||
for name, info in MESH_ASSETS.items():
|
||||
path = info["path"]
|
||||
default_size = info.get("default_size")
|
||||
mesh = unreal.load_asset(path)
|
||||
|
||||
if not mesh:
|
||||
results.append(f"{name}: ⚠️ 无法加载")
|
||||
continue
|
||||
|
||||
# 获取 Bounding Box (UE5 Box 对象有 min/max,没有 origin/extent)
|
||||
bb = mesh.get_bounding_box()
|
||||
bmin = bb.min
|
||||
bmax = bb.max
|
||||
|
||||
mn_x, mn_y, mn_z = bmin.x, bmin.y, bmin.z
|
||||
mx_x, mx_y, mx_z = bmax.x, bmax.y, bmax.z
|
||||
size_x = mx_x - mn_x
|
||||
size_y = mx_y - mn_y
|
||||
size_z = mx_z - mn_z
|
||||
|
||||
# 判断锚点类型:
|
||||
# CENTER: min ≈ (-half, -half, -half),对称包围盒
|
||||
# CORNER: min ≈ (0, 0, 0),锚点在角落
|
||||
# CENTER_BOTTOM: min ≈ (-half, -half, 0),锚点在底部中心
|
||||
pivot_type = "UNKNOWN"
|
||||
offset_desc = ""
|
||||
|
||||
if default_size:
|
||||
dw, dh, dd = default_size
|
||||
half_w, half_h, half_d = dw / 2, dh / 2, dd / 2
|
||||
tol = 5 # cm 容差
|
||||
|
||||
is_corner = (abs(mn_x) < tol and abs(mn_y) < tol and abs(mn_z) < tol)
|
||||
is_center = (abs(mn_x + half_w) < tol and abs(mn_y + half_h) < tol
|
||||
and abs(mn_z + half_d) < tol)
|
||||
is_center_bot = (abs(mn_x + half_w) < tol and abs(mn_y + half_h) < tol
|
||||
and abs(mn_z) < tol)
|
||||
|
||||
if is_corner:
|
||||
pivot_type = "CORNER"
|
||||
elif is_center:
|
||||
pivot_type = "CENTER"
|
||||
elif is_center_bot:
|
||||
pivot_type = "CENTER_BOTTOM"
|
||||
else:
|
||||
pivot_type = "OTHER"
|
||||
offset_desc = f" (min=({mn_x:.0f},{mn_y:.0f},{mn_z:.0f}), expected corner=0/center=-{half_w:.0f})"
|
||||
else:
|
||||
# 无 default_size,用 min 值推断
|
||||
tol = 5
|
||||
if abs(mn_x) < tol and abs(mn_y) < tol and abs(mn_z) < tol:
|
||||
pivot_type = "CORNER?"
|
||||
elif mn_z < -tol:
|
||||
pivot_type = "CENTER?"
|
||||
else:
|
||||
pivot_type = "CENTER_BOTTOM?"
|
||||
offset_desc = f" (no default_size, inferred)"
|
||||
|
||||
results.append(
|
||||
f"{name}:\n"
|
||||
f" min=({mn_x:.1f}, {mn_y:.1f}, {mn_z:.1f}) "
|
||||
f"max=({mx_x:.1f}, {mx_y:.1f}, {mx_z:.1f}) "
|
||||
f"size=({size_x:.0f}, {size_y:.0f}, {size_z:.0f})\n"
|
||||
f" default_size={default_size} → pivot={pivot_type}{offset_desc}"
|
||||
)
|
||||
|
||||
print("=" * 60)
|
||||
print("BSP 资产锚点检测结果")
|
||||
print("=" * 60)
|
||||
for r in results:
|
||||
print(r)
|
||||
print("=" * 60)
|
||||
|
||||
# 保存结果
|
||||
out_path = Path(__file__).parent / "output" / "pivot_check.txt"
|
||||
out_path.parent.mkdir(exist_ok=True)
|
||||
with open(out_path, "w", encoding="utf-8") as f:
|
||||
f.write("BSP 资产锚点检测结果\n")
|
||||
f.write("=" * 60 + "\n")
|
||||
for r in results:
|
||||
f.write(r + "\n")
|
||||
print(f"\n结果已保存: {out_path}")
|
||||
|
||||
|
||||
# 供命令行调用
|
||||
if __name__ == "__main__":
|
||||
check_pivots()
|
||||
Reference in New Issue
Block a user