feat: draw.py 直接读取 move_camera.txt,修改后重启即生效
draw.py 启动时优先读取 input/move_camera.txt(实时文件), 不存在或为空时回退到 display.txt header 中的缓存数据。 改动 move_camera.txt 后只需重启动画窗口(关掉旧窗口重新 run_dynamics.py),无需重新跑模拟。
This commit is contained in:
@@ -555,13 +555,46 @@ print(f"[draw] 渲染方式: {mode_str}")
|
|||||||
print(f"[draw] 绘图参数: ball_radius={ball_radius}, box_color=({box_color_r:.2f},{box_color_g:.2f},{box_color_b:.2f}), alpha={alpha_list}")
|
print(f"[draw] 绘图参数: ball_radius={ball_radius}, box_color=({box_color_r:.2f},{box_color_g:.2f},{box_color_b:.2f}), alpha={alpha_list}")
|
||||||
|
|
||||||
|
|
||||||
# 运动相机(速度段驱动)
|
# 运动相机(速度段驱动):优先读取 move_camera.txt,其次用 display.txt header 缓存
|
||||||
|
import re as _re
|
||||||
|
|
||||||
|
def _load_move_camera_txt():
|
||||||
|
"""直接读取 input/move_camera.txt(与 output 同级的 input 目录)。"""
|
||||||
|
input_dir = os.path.join(os.path.dirname(output_dir), "input")
|
||||||
|
cam_path = os.path.join(input_dir, "move_camera.txt")
|
||||||
|
if not os.path.exists(cam_path):
|
||||||
|
return None
|
||||||
|
segs = []
|
||||||
|
with open(cam_path, "r", encoding="utf-8") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
m = _re.match(r'(\d+)\s*-\s*(\d+)', line)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
start, end = int(m.group(1)), int(m.group(2))
|
||||||
|
v, r = [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]
|
||||||
|
for i, axis in enumerate(['x', 'y', 'z']):
|
||||||
|
m2 = _re.search(r'v' + axis + r'\s*=\s*([-\d.]+)', line)
|
||||||
|
if m2: v[i] = float(m2.group(1))
|
||||||
|
m2 = _re.search(r'r' + axis + r'\s*=\s*([-\d.]+)', line)
|
||||||
|
if m2: r[i] = float(m2.group(1))
|
||||||
|
if any(v) or any(r):
|
||||||
|
segs.append({"start": start, "end": end, "v": v, "r": r})
|
||||||
|
return segs if segs else None
|
||||||
|
|
||||||
|
# 先试 move_camera.txt 直读,没有则用 display.txt 缓存
|
||||||
|
_CAM_MOTION = _load_move_camera_txt()
|
||||||
|
if not _CAM_MOTION:
|
||||||
_CAM_MOTION = json.loads(h.get("camera_keyframes", "null")) if h.get("camera_keyframes") else None
|
_CAM_MOTION = json.loads(h.get("camera_keyframes", "null")) if h.get("camera_keyframes") else None
|
||||||
if _CAM_MOTION:
|
if _CAM_MOTION:
|
||||||
_cam_center = [0.0, 0.0, 0.0]
|
_cam_center = [0.0, 0.0, 0.0]
|
||||||
_cam_elev = initial_camera["elevation"]
|
_cam_elev = initial_camera["elevation"]
|
||||||
_cam_azim = initial_camera["azimuth"]
|
_cam_azim = initial_camera["azimuth"]
|
||||||
_cam_dist = initial_camera["distance"]
|
_cam_dist = initial_camera["distance"]
|
||||||
|
src = "move_camera.txt" if _load_move_camera_txt() else "display.txt header"
|
||||||
|
print(f"[draw] 运动相机已启用(数据来源: {src},{len(_CAM_MOTION)} 段)")
|
||||||
|
|
||||||
|
|
||||||
def _update_motion_camera(f_idx):
|
def _update_motion_camera(f_idx):
|
||||||
|
|||||||
@@ -105,4 +105,4 @@ box_color_b: 0.85
|
|||||||
camera_distance: 40.0 # 摄像机到场景中心的距离
|
camera_distance: 40.0 # 摄像机到场景中心的距离
|
||||||
camera_elevation: 0 # 俯仰角(度),负值=俯视
|
camera_elevation: 0 # 俯仰角(度),负值=俯视
|
||||||
camera_azimuth: 0 # 方位角(度)
|
camera_azimuth: 0 # 方位角(度)
|
||||||
move_camera: 0 # 0=固定视角, 1=按 move_camera.txt 运动
|
move_camera: 1 # 0=固定视角, 1=按 move_camera.txt 运动
|
||||||
|
|||||||
@@ -5,5 +5,4 @@
|
|||||||
# rx → elevation(俯仰), ry → azimuth(方位), rz → (预留)
|
# rx → elevation(俯仰), ry → azimuth(方位), rz → (预留)
|
||||||
#
|
#
|
||||||
# 示例:前60帧向右平移+绕x旋转,30-90帧向上平移+绕y绕z旋转
|
# 示例:前60帧向右平移+绕x旋转,30-90帧向上平移+绕y绕z旋转
|
||||||
1-60 vx=1.0 rx=10
|
1-200 vx=0.01
|
||||||
30-90 vy=2.0 ry=20 rz=10
|
|
||||||
|
|||||||
Reference in New Issue
Block a user